Haskell 类的ghci意外行为实例

Haskell 类的ghci意外行为实例,haskell,instance,gchi,Haskell,Instance,Gchi,我一直在浏览Bryan O'Sullivan及其同事的“真实世界Haskell”,在Windows下遇到了我称之为GHCi 7.8.3版的意外“松弛”。 I“:加载”以下内容- module JSONModule where data JValue = JNumber Double | JBool Bool deriving ( Show, Eq, Ord ) class JSON a where toJValue :: a ->

我一直在浏览Bryan O'Sullivan及其同事的“真实世界Haskell”,在Windows下遇到了我称之为GHCi 7.8.3版的意外“松弛”。 I“:加载”以下内容-

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应该告诉我放风筝,因为fromJValue有两个例子。 的确,如果我具体说明的话

fromJValue it :: Either String Bool
我是对的。问题似乎是双重价值。消除JSON双实例,并向JValue添加一个JChar Char构造函数和一个JSON Char的对应实例,我从ghci获得了预期的“不明确”响应。 所以我认为有一个bug。
评论?感谢……

了解真实情况:

[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"
[1/1]编译JSONModule(test.hs,解释)
好的,已加载模块:JSONModule。
>:设置-墙
>:t fromJValue(toJValue False)
fromJValue(toJValue False)::JSON a=>字符串a
>fromJValue(toJValue False)
:6:2:警告:
将以下约束默认为键入'Double'
(JSON a0)源于在6:2-28使用“it”
(显示a0)因在6:2-28使用“打印”而产生
在'print'的第一个参数中,即'it'
在交互式GHCi命令的stmt中:打印它
左“不是JSON编号”

如您所见,ghc将不明确的类型变量默认为Double。当没有Double的实例时,它会给出不明确的类型错误,这是因为默认行为仅将默认约束设置为Integer或Double,因为这些是最有用(或常见)的情况

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

大约,当一个类型在其他方面不明确并且具有正确形式的类约束时,具有此扩展的GHC将尝试将其默认为符合
()、Integer、Double
的第一个类型

如果没有扩展的DefaultRules扩展,例如默认情况下在模块文件中,默认仍然可以发生,但是要求更严格(必须至少涉及一个数值类,并且不尝试使用
()
),并且只适用于一组固定的类,而不适用于您自己定义的任何类