我一直在经历布莱恩·奥沙利文和合作伙伴"真实世界哈斯克尔,"并且遇到了我所谓的意外的松弛'在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的回应。 所以我认为有一个错误。 评论?感谢...
答案 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.