[Haskell-cafe] Typeclasses question in "Real World Haskell" book

Angel de Vicente angelv at iac.es
Mon Jul 26 15:03:10 EDT 2010


Hi,

thanks for the answer. This is my first attempt at Typeclasses, and I 
think there is something "deep" that I don't understand...

On 26/07/10 15:03, Daniel Fischer wrote:
>> class JSON a where
>>       toJValue :: a ->  JValue
>>       fromJValue :: JValue ->  Either JSONError a
>>
>> instance JSON JValue where
>>       toJValue = id
>>       fromJValue = Right
>>
>> instance JSON Bool where
>>       toJValue = JBool
>>       fromJValue (JBool b) = Right b
>>       fromJValue _ = Left "not a JSON boolean"
>>
>>
>> I don't understand how the JSON typeclass is defined, in particular the
>> fromJValue definition.
>
> Given a JValue and a type
> (like Bool, JValue, String, Maybe [(Integer, ())]), fromJValue returns
> either

a JValue and a type???

>> For instance, when defining the instance for Bool types, then I
>> understand that both functions (toJValue and fromJValue) will be called
>> upon when we supply a Bool type, but then the (JBool b) type in function
>> fromJValue doesn't match....
>
> fromJValue always takes a JValue as argument. That JValue can be a wrapped
> String, a wrapped Bool, a wrapped number (Double), ...

so, fromJValue takes a JValue and a type, or only a JValue?  I was 
assuming the second, but then my misunderstanding kicks in, I guess. 
I'll try to explain myself. When defining

class JSON a [...], then I thought that for an instance I would have to 
identify the type of that instance and that all functions would work on 
that type. Thus, when defining

instan JSON Bool [...] I was expecting that all the function definitions 
would have as argument a Bool. toJValue is no problem there, but I don't 
see the fromJValue definition, since this matches against either (JBool 
b) or _ , but not a Bool...

Another misunderstading on my side: if I call fromJValue (JBool True), 
which instance ofr fromJValue should be used: instance JSON JValue or 
instance JSON Bool. If we only look at the signature of the fromJValue 
functions, then both could match?

>> *Main>  fromJValue False
>>
>> <interactive>:1:11:
>>       Couldn't match expected type `JValue' against inferred type `Bool'
>>       In the first argument of `fromJValue', namely `False'
>>       In the expression: fromJValue False
>>       In the definition of `it': it = fromJValue False
>
> That one should be pretty clear, fromJValue expects a JValue as argument
> and gets a Bool, it's like calling

Yes, but I guess you see why I try this given my misunderstanding above?

>> *Main>  fromJValue (JBool False)
>>
>> <interactive>:1:0:
>>       Ambiguous type variable `a' in the constraint:
>>         `JSON a' arising from a use of `fromJValue' at
>> <interactive>:1:0-23 Probable fix: add a type signature that fixes these
>> type variable(s) *Main>
>
> That's less easy.
> The compiler/interpreter doesn't know which result type to use.
>
> fromJValue :: JSON a =>  JValue ->  Either JSONError a
>
> with which type should a be instantiated, should it use
> - JValue, in which case the result would be
> Right (JBool False)
>
> - Bool, in which case the result would be
> Right False
>
> - String, in which case the result woulde be something like
>      No instance for (JValue [Char])
>        arising from a use of `fromJValue' at ...
>
> (unless you have such an instance in scope, then it would be something like
> Left "not a JSON string")
>
> - Int, in which case you'd get analogous behaviour
> - ...
>
>>
>>
>>
>> Any pointers?
>
> In an actual programme, there is usually enough context to fix the type
> variable a, then the compiler/interpreter knows what to do.
> At the prompt or when there isn't enough context otherwise, you need to
> explicitly tell the compiler/interpreter which type to use,
>
> *Main>  fromJValue (JBool False) :: Either JSONError Bool
> Right False
> *Main>  fromJValue (JBool False) :: Either JSONError JValue
> Right (JBool False)

Ah... OK, I think with these two examples the whole thing starts to make 
sense.

When defining

instance JSON Bool

then this doesn't mean that the functions need to work just on Bool's, 
but rather that wherever there is an "a" in the typeclass definition, 
then this should be instantiated to a Bool, correct?



And now that we are at it... In the next page, 152 there is the 
following instance definition, but no explanation is (I think) given of 
what it means:

instance (JSON a) => JSON [a] where

until then all instance definitions where of the type

instance JSON Int where ...

How should I read that definition?

Thanks for you help,
Ángel de Vicente
-- 
http://www.iac.es/galeria/angelv/

High Performance Computing Support PostDoc
Instituto de Astrofísica de Canarias
---------------------------------------------------------------------------------------------
ADVERTENCIA: Sobre la privacidad y cumplimiento de la Ley de Protección de Datos, acceda a http://www.iac.es/disclaimer.php
WARNING: For more information on privacy and fulfilment of the Law concerning the Protection of Data, consult http://www.iac.es/disclaimer.php?lang=en



More information about the Haskell-Cafe mailing list