# How to use RequiredTypeArguments with typeclasse methods?

**URL:** <https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187>\
**Category:** Uncategorized\
**Created:** [May 28, 2025, 11:18am UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187 "2025-05-28T11:18:17Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![rumaan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/rumaan/32/5158_2.png) [@rumaan](https://discourse.haskell.org/u/rumaan)\
**Post date:** [May 28, 2025, 11:18am UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187/1 "2025-05-28T11:18:17Z")

</div>

Hi everyone,  
I’m reading the [GHC Manual](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/required_type_arguments.html#relation-to-typeapplications) on `RequiredTypeArguments` and it illustrates the implementation of the proposal with the following:

> One advantage of required type arguments is that they are never ambiguous. Consider the type of `Foreign.Storable.sizeOf`:
> 
> `sizeOf :: forall a. Storable a => a -> Int`
> 
> The value parameter is not actually used, its only purpose is to drive type inference. At call sites, one might write `sizeOf (undefined :: Bool)` or `sizeOf @Bool undefined`. Either way, the `undefined` is entirely superfluous and exists only to avoid an ambiguous type variable.
> 
> With [`RequiredTypeArguments`](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/required_type_arguments.html#extension-RequiredTypeArguments), we can imagine a slightly different API:
> 
> `sizeOf :: forall a -> Storable a => Int`
> 
> If `sizeOf` had this type, we could write `sizeOf Bool` without passing a dummy value.

Which sounds great. So I have tried to replicate it:

```haskell
{-# LANGUAGE RequiredTypeArguments #-}

module Main where

import Data.Kind (Type)

class Storable (a :: Type) where
  sizeOf :: forall a -> Int
  
instance Storable Int where
  sizeOf _ = 8

```

Unfortunately I get all manners of type errors:

```haskell
Main.hs:8:3: error: [GHC-39999]
    • Could not deduce ‘Storable a0’
      from the context: Storable a
        bound by the type signature for:
                   sizeOf :: forall a {k}. Storable a => forall (a1 :: k) -> Int
        at Main.hs:8:3-27
      The type variable ‘a0’ is ambiguous
    • In the ambiguity check for ‘sizeOf’
      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
      When checking the class method:
        sizeOf :: forall a {k}. Storable a => forall (a1 :: k) -> Int
      In the class declaration for ‘Storable’
  |
8 | sizeOf :: forall a -> Int
  | ^^^^^^^^^^^^^^^^^^^^^^^^^

```

Am I missing something? Is there a complementary extension to enable?

Here is a playground link: [https://play.haskell.org/saved/cotQbJ5Z](https://play.haskell.org/saved/cotQbJ5Z)

---

<div class="post-metadata">

**Author:** ![TeofilC](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/teofilc/32/3987_2.png) [@TeofilC](https://discourse.haskell.org/u/TeofilC)\
**Post date:** [May 28, 2025, 11:22am UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187/2 "2025-05-28T11:22:55Z")

</div>

It’s a bit ugly but you can do this: [Haskell Playground](https://play.haskell.org/saved/OrL7nSWL)

Maybe there is a better way though?

The tricky thing is that `forall a` is shadowing the `a` you are giving an instance for

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [May 28, 2025, 11:31am UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187/3 "2025-05-28T11:31:22Z")

</div>

The recommended way, currently, is just to use a separate function:

```haskell
{-# LANGUAGE RequiredTypeArguments, AllowAmbiguousTypes #-}

import Data.Kind (Type)

class Storable (a :: Type) where
  _sizeOf :: Int
  
instance Storable Int where
  _sizeOf = 8

sizeOf :: forall a -> Storable a => Int
sizeOf a = _sizeOf @a

```

Source: [https://github.com/ghc-proposals/ghc-proposals/pull/267#issuecomment-528449235](https://github.com/ghc-proposals/ghc-proposals/pull/267#issuecomment-528449235)

---

<div class="post-metadata">

**Author:** ![rumaan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/rumaan/32/5158_2.png) [@rumaan](https://discourse.haskell.org/u/rumaan)\
**Post date:** [May 28, 2025, 11:35am UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187/4 "2025-05-28T11:35:16Z")

</div>

Ok I see! I think I prefer @TeofilC’s solution at the moment. Pity none of them are in the guide. 🙂

My thanks to you both!

---

<div class="post-metadata">

**Author:** ![jmcarthur](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jmcarthur/32/3283_2.png) [@jmcarthur](https://discourse.haskell.org/u/jmcarthur)\
**Post date:** [May 28, 2025, 11:42am UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187/5 "2025-05-28T11:42:55Z")

</div>

@TeofilC’s approach is what I do, and although I hate that I have to do it, there have been no sharp corners so far.

---

<div class="post-metadata">

**Author:** ![rumaan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/rumaan/32/5158_2.png) [@rumaan](https://discourse.haskell.org/u/rumaan)\
**Post date:** [May 28, 2025, 11:50am UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187/6 "2025-05-28T11:50:30Z")

</div>

Cheers, thanks for the feedback. 🙂

---

<div class="post-metadata">

**Author:** ![evincar](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/evincar/32/3594_2.png) [@evincar](https://discourse.haskell.org/u/evincar)\
**Post date:** [May 29, 2025, 2:18pm UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187/7 "2025-05-29T14:18:54Z")

</div>

You can write an explicit quantifier on an `instance` definition (and I do!) like `instance forall a b. (Semigroup a, Semigroup b) => Semigroup (a, b)`. So I feel like it should also work to write one on a `class`, in which case you could spell out which quantifier you want.

1. `class forall (a :: Type). Storable a where sizeOf :: Int`
  - `sizeOf :: forall a. Storable a => Int`
  - `instance Storable Int where sizeOf = 8`

2. `class forall (a :: Type) -> Storable a where sizeOf :: Int`
  - `sizeOf :: forall a -> Storable a => Int`
  - `instance Storable Int where sizeOf Int = 8` (or `sizeOf _ = 8`)

For consistency it would then also be possible to write `instance forall a -> …`, which is a little weird, but I don’t think it causes any actual problems for instance resolution.

---

<div class="post-metadata">

**Author:** ![viktor](https://avatars.discourse-cdn.com/v4/letter/v/d6d6ee/32.png) [@viktor](https://discourse.haskell.org/u/viktor)\
**Post date:** [July 14, 2025, 7:44am UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187/8 "2025-07-14T07:44:56Z")

</div>

I asked an essentially identical question on the haskell-cafe list, and got an answer identical to @TeofilC’s approach. Works for me, and I would strongly support some text in the guide that covers this topic. Anyone care to propose an MR?

It is also I think worth pointing out that it is [possible to write wrappers](https://play.haskell.org/saved/Bj0yIoRh) in the opposite direction, i.e. calling the function with visible type arguments from a context where a term of the type is available.

---

<div class="post-metadata">

**Author:** ![treeowl](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/treeowl/32/1813_2.png) [@treeowl](https://discourse.haskell.org/u/treeowl)\
**Post date:** [August 2, 2025, 2:06pm UTC](https://discourse.haskell.org/t/how-to-use-requiredtypearguments-with-typeclasse-methods/12187/9 "2025-08-02T14:06:12Z")

</div>

The fact that `~` is lifted could have a performance impact in some cases. I wish we had access to the Core unlifted type equality.
