I’ve been getting into the nitty gritty of the haskell typesystem and trying to get at the fine points of type classes. I’ve learned a heap, but I’m hitting a wall on the following pieces of code.
Using these Class and Instance definitions:
class Show a => C a where
f :: Int -> a
instance C Integer where
f x = 1
instance C Char where
f x = if x < 10 then 'c' else 'd'
Why is it that this passes the type checker:
g :: C a => a -> Int -> a
g x y = f y
yes :: C a => a -> Int -> String
yes x y = show (g x y)
but this doesn’t?
g :: C a => a -> Int -> String
g x y = show(f y)
I find the second alternative much more readable, and it seems to be only a minor difference (note the type signatures). However, trying to get that past the typechecker results in:
*Main> :l typetests.hs
[1 of 1] Compiling Main ( typetests.hs, interpreted )
typetests.hs:11:14:
Ambiguous type variable `a0' in the constraints:
(C a0) arising from a use of `f' at typetests.hs:11:14
(Show a0) arising from a use of `show' at typetests.hs:11:9-12
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `show', namely `(f y)'
In the expression: show (f y)
In an equation for `g': g x y = show (f y)
Failed, modules loaded: none.
And I don’t understand why.
Note: Please don’t ask “What are you trying to do?” I would hope it is obvious that I’m just messing around in an abstract context in order to probe the way this language works. I have no goal in mind other than learning something new.
Thanks
This is where a fun toy comes into play. Consider the standard Prelude function
asTypeOf.It just returns its first argument, no matter what the second argument is. But the type signature on it places the additional constraint that both of its arguments must be the same type.
Now, GHC knows what the type of
f yis. It’s the same as the type of the first argument tog. Without that information, well, you get the error message you saw. There just wasn’t sufficient information to determine the type off y. And because the type is important (it’s used to determine which instance to use forshow), GHC needs to know what type you mean to generate code.