On Monday 26 July 2010 15:16:36, Angel de Vicente wrote: > Hi, > > I'm stuck at page 151 of Real World Haskell and hoping that perhaps some > of you can give me a hand here... > > The code that is giving me trouble is below. > > data JValue = JString String > > | JNumber Double > | JBool Bool > | JNull > | JObject [(String, JValue)] > | JArray [JValue] > > deriving (Eq, Ord, Show) > > type JSONError = String > > 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 Left errormessage or Right (value of desired 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), ... Depending on the result type (Either JSONError a), it returns a wrapped value of type a [Right a] or a wrapped error message [Left JSONError] > > toJValue is no problem, but I cannot understand how fromJValue is > supposed to work, and the comments in the online book > (http://book.realworldhaskell.org/read/using-typeclasses.html) don't > help with this either. > > *Main> :load ch6 > [1 of 1] Compiling Main ( ch6.hs, interpreted ) > Ok, modules loaded: Main. > *Main> toJValue False > JBool False > *Main> :type it > it :: JValue > *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 fromInteger True > *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) > > Thanks a lot, > Ángel de Vicente _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe