ghci类的意外行为实例

时间:2015-03-06 05:33:11

标签: haskell instance gchi

我一直在经历布莱恩·奥沙利文和合作伙伴"真实世界哈斯克尔,"并且遇到了我所谓的意外的松弛'在Windows下的GHCi,版本7.8.3。 我":已加载"以下 -

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"

然后,在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"

虽然这是事实,但这并不是人们所期望的。我认为ghci应该告诉我放风筝,因为有两个来自于J.Value的实例。 的确,如果我指定

fromJValue it :: Either String Bool

我说错了。问题似乎是doubleToJValue。消除了JSON Double实例,并将JChar Char构造函数添加到JValue,以及JSON Char的相应实例,我得到了预期的“模糊”'来自ghci的回应。 所以我认为有一个错误。 评论?感谢...

2 个答案:

答案 0 :(得分:4)

这不是错误,而是ExtendedDefaultRules extension的结果,默认情况下在GHCi提示符处启用,但不在文件中启用。

近似地,当一个类型不明确且具有正确形式的类约束时,具有此扩展名的GHC将尝试将其默认为适合(), Integer, Double的第一个类型。

没有ExtendedDefaultRules扩展名,例如默认情况下在模块文件中,默认情况仍然可能发生,但要求更严格(必须至少涉及一个数字类,并且未尝试() )并且只适用于一组固定的类,而不是你自己定义的类。

答案 1 :(得分:3)

要了解到底发生了什么:

[1 of 1] Compiling JSONModule       ( test.hs, interpreted )
Ok, modules loaded: JSONModule.
>:set -Wall
>:t fromJValue (toJValue False)
fromJValue (toJValue False) :: JSON a => Either String a
> fromJValue (toJValue False)

<interactive>:6:2: Warning:
    Defaulting the following constraint(s) to type `Double'
      (JSON a0) arising from a use of `it' at <interactive>:6:2-28
      (Show a0) arising from a use of `print' at <interactive>:6:2-28
    In the first argument of `print', namely `it'
    In a stmt of an interactive GHCi command: print it
Left "not a JSON number"

如您所见,ghc将模糊类型变量默认为Double。当没有Double实例时,它给出模糊类型错误的原因是因为默认行为只是默认约束为Integer或Double,因为这些是已被发现最有用(或常见)的​​情况。 More info on defaulting.