I've been going through Bryan O'Sullivan's and co's "Real World Haskell," and came across what I would call unexpected 'laxness' on the part of GHCi, version 7.8.3, under Windows. I ":loaded" the following -
module JSONModule where
data JValue = JNumber Double
| JBool Bool
deriving ( Show, Eq, Ord )
class JSON a where
toJValue :: a -> JValue
fromJValue :: JValue -> Either String a
fromJBool (JBool b) = Right b
fromJBool _ = Left "not a JSON boolean"
instance JSON Double where
toJValue = JNumber
fromJValue = doubleToJValue id
instance JSON Bool where
toJValue = JBool
fromJValue = fromJBool
doubleToJValue :: (Double -> a) -> JValue -> Either String a
doubleToJValue f (JNumber v) = Right (f v)
doubleToJValue _ _ = Left "not a JSON number"
Then, in ghci :
*JSONModule> :r
[1 of 1] Compiling JSONModule ( JSONModule.hs, interpreted )
Ok, modules loaded: JSONModule.
*JSONModule> toJValue False
JBool False
*JSONModule> fromJValue it
Left "not a JSON number"
While this is true, it is not what would have expected. I think ghci should have told me to fly a kite, as there were 2 instances for fromJValue. Indeed, if I specify
fromJValue it :: Either String Bool
I get Right False. The issue seems to be doubleToJValue. Eliminating the JSON Double instance, and adding a JChar Char constructor to JValue, and a corresponding instance of JSON Char, I get the expected 'ambiguous' response from ghci. So I think there is a bug. Comments? Thanks...
This is not a bug, but a result of the ExtendedDefaultRules
extension, which is enabled by default at the GHCi prompt, but not in files.
Approximately, when a type is otherwise ambiguous and has class constraints of the right form, GHC with this extension will try defaulting it to the first type which fits from (), Integer, Double
.
Without the ExtendedDefaultRules
extension, such as in module files by default, defaulting can still happen, but the requirements are stricter (at least one numeric class must be involved, and ()
isn't tried) and will only apply to a fixed set of classes, not any you define yourself.