Search code examples
haskelltype-inferencegadt

Haskell type inference with GADTs and typeclass constraints on type variables


I defined a custom GADT where the type constructor has a type class constraint on the type variable, like this:

data MyGadt x where
  Sample :: Show a => a -> MyGadt a

Now, if I define the following two functions:

foo (Sample a) = show a

bar a = Sample a

GHC infers types for them that are a bit irritating to me. foo :: MyGadt x -> [Char] doesn't mention the Show constraint for x, while bar :: Show a => a -> MyGadt a does require the constraint to be mentioned explicitly.

I was assuming that I don't have to mention the constraint because it is declared in the GADT definition. The only thing I can think of being part of the reason is the position of the GADT in the function. I'm not super deep into that but as far as I understand it, MyGadt is in positive position in foo and in negative position in bar.

When do I have to mention the type class constraints explicitly, and when does GHC figure it out itself based on the constraint on the GADTs type constructor?


Solution

  • It's the whole point of using a GADT that you want the constraint to show up in the signature of bar, instead of foo. If you don't want that, then you can use a plain old newtype instead:

    newtype MyAdt = Sample a
    
    foo :: Show a => MyAdt a -> String
    foo (Sample a) = show a
    
    bar :: a -> MyAdt a
    bar = Sample
    

    Having the constraint in neither foo nor bar clearly can't work, because then you would be able to e.g.

    showFunction :: (Integer -> Integer) -> String
    showFunction = foo . bar