Вопрос

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?

Это было полезно?

Решение 2

Your problem is the scope of type variables. When you write

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

The first line (the type declaration for bar) has its own scope for type variables, and on the second line it sees the :: b as a different b from the Rel a b.

If you enable the ScopedTypeVariables extension and declare your type as

bar :: forall a b. (Rel a b) => a -> b

Then the b's scope extends over the definition of bar.

Другие советы

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top