3
votes

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.

1
Please give the type of foo here, just for completeness. - Joachim Breitner
foo, it's actually a parser, it's a bit more complicated in my code I was trying to simplify here. Now it actually compile even without the ScopedTypeVariables, but as you said in the other post I probably misunderstood the way readPresc works because now I got Exception: Prelude.read: no parse When I try to read a string as MyType. - user1544128
ok so in my case to be correct should be [foo (read r :: a ), ""], hope will be helpful to some other newbies :) - user1544128
Sorry, but I find your edit confusing. Can you rephrase that as a question? - Joachim Breitner
I rephrase it, I hope now it's clearer :) - user1544128

1 Answers

6
votes

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.