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 foo has type a -> MyType a. The compiler can figure out from the expected type signature of readsPrec that the call to foo ought to return a MyType a, and hence (by the type of foo), the expression read r ought to have type a.
But why does it fail when you annotate that with :: a? Because type variables are local to the type signature they appear in. So the a there is totally unrelated to the a in the instance heade and with read r :: a you are actually saying: The expression read r can have any arbitrary type. But an arbitrary type has no Read instance, hence the error message. In the message, the compiler renamed the inner a to a2 to avoid a name clash.
Your code can work as expected, though, if you add {-# LANGUAGE ScopedTypeVariables #-} to the module header. Now, the a in read r :: a refers to the type of a in 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.
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