I was just starting having fun with haskell when I got stuck.
I’m trying to make my new data type (let’s call it MyType) instance of the Read class. Mytype is a type constructor, so it takes another type as parameter. I wanted to write this kind of code
instance (Read a) => Read (MyType a) where
readsPrec _ r = [foo (read r :: a ), r]
but it gives me the following error
Could not deduce (Read a2) arising from a use of `read' from the context (Read a).
I thought that since a is Readable I could just infer it, but apparently I’m wrong. Any ideas?
EDIT:
I have changed the previous code to
readsPrec _ r = [foo (read r :: a ), ""]
so if I type: read "myString" :: MyType a it works perfectly fine.
Now I was hoping that if I would use read "myString" within a context, I shouldn’t have to specify the type to read. But the problem is that with
bar (read myString) a
where bar:: MyType a -> a -> MyType a, I got
Ambiguos variable type.
Is it possible to do something like that without getting that kind of error?
I hope it’s clearer now, I’m trying to simplify the code but I hope I didn’t omit anything crucial.
The code actually typechecks if written as
instance (Read a) => Read (MyType a) where readsPrec _ r = [(foo (read r),r)]if
foohas typea -> MyType a. The compiler can figure out from the expected type signature ofreadsPrecthat the call tofooought to return aMyType a, and hence (by the type offoo), the expressionread rought to have typea.But why does it fail when you annotate that with
:: a? Because type variables are local to the type signature they appear in. So theathere is totally unrelated to theain the instance heade and withread r :: ayou are actually saying: The expressionread rcan have any arbitrary type. But an arbitrary type has noReadinstance, hence the error message. In the message, the compiler renamed the inneratoa2to avoid a name clash.Your code can work as expected, though, if you add
{-# LANGUAGE ScopedTypeVariables #-}to the module header. Now, theainread r :: arefers to the type ofain the instance header and all goes well.Note that you are not using readsPrec correctly, but I guess that is not part of the question.