Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding type signature causes compile error

In Haskell I can define a function like this:

foo :: Int -> Int
foo n = n + 1

If I want to be anal, I can add a type signature to the last line like this:

foo :: Int -> Int
foo n = n + 1 :: Int

I can also define a function bar in terms of a type class like this:

class Rel a b where
  aToB :: a -> b

bar :: (Rel a b) => a -> b
bar a = aToB a

However if I add a type signature to the implementation of bar (a benign change, or so I thought), I get a compile error.

bar :: (Rel a b) => a -> b
bar a = aToB a :: b

And here's the error:

Could not deduce (Rel a b1) arising from a use of `aToB'
from the context (Rel a b)
  bound by the type signature for bar :: Rel a b => a -> b
  at q.hs:79:1-23
Possible fix:
  add (Rel a b1) to the context of
    an expression type signature: b1
    or the type signature for bar :: Rel a b => a -> b
In the expression: aToB val :: b
In an equation for `bar': bar val = aToB val :: b

I think the error means that the compiler isn't convinced that the b in the implementation of bar is the same as the b in the type signature of bar. However, I'm not sure why that would be the case.

Why do I get this compile error when I add a type signature to my function implementation?

like image 760
jcarpenter2 Avatar asked Jan 21 '14 22:01

jcarpenter2


1 Answers

You actually need a language extension and a bit of extra syntax to make the two b type variables be the same:

{-# LANGUAGE ScopedTypeVariables #-}
bar :: forall a b . (Rel a b) => a -> b
bar a = aToB a :: b

The forall is essentially saying "a and b should be in scope for the whole definition", and ScopedTypeVariables is needed to be allowed to use this syntax.

I guess this is really a historic wart in the design of the language.

like image 172
GS - Apologise to Monica Avatar answered Sep 22 '22 00:09

GS - Apologise to Monica