Sorry to bother you with this simple problem. I'm trying to learn how the type family extension works. When I fool around with it I encountered an error I couldn't figure out why.
class Foo a b c where
data T a b c :: *
f :: a -> T a b c
g :: T a b c -> b
h :: c -> a -> b
h c a = g $ f a
Error message:
Could not deduce (Foo a b c0) arising from a use of ‘g’
from the context (Foo a b c)
bound by the class declaration for ‘Foo’
at DB/Internal/Typecast.hs:(17,1)-(25,19)
The type variable ‘c0’ is ambiguous
Relevant bindings include
a :: a (bound at DB/Internal/Typecast.hs:25:9)
h :: c -> a -> b (bound at DB/Internal/Typecast.hs:25:5)
In the expression: g
In the expression: g $ f a
In an equation for ‘h’: h c a = g $ f a
I don't understand how is c ambiguous in T a b c
for g
. Can't the compiler get the type of c
from the T a b c
of f
?
I just want the composite of g . f
Note that in the definition
h :: c -> a -> b
h c a = g $ f a
there is no restriction that f
and g
refer to the same instance that you are defining h
for. (And this flexibility is often useful for defining instances.)
From type inference, the result of g
is restricted to be of the same type b
, and the argument of f
is restricted to be of type a
, but there's nothing saying that the T a b c
passed from one to the other is using the same c
!
To fix this in this case, you can enable ScopedTypeVariables
and do
h c a = g (f a :: T a b c)
Note that this works because data families are "injective" (the type arguments of a data family can be deduced from the final type). If you had used a type family instead, even this wouldn't work, since then T a b c
would not necessarily determine c
at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With