代码之家  ›  专栏  ›  技术社区  ›  peter a g

ghci类的意外行为实例

  •  2
  • peter a g  · 技术社区  · 10 年前

    我一直在读布莱恩·奥沙利文(Bryan O’Sullivan)和合作伙伴的《真实世界哈斯克尔》(Real World Haskell),在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应该告诉我放风筝,因为fromJValue有两个例子。 的确,如果我指定

    fromJValue it :: Either String Bool
    

    我得到了对错。问题似乎是双重价值。消除了JSON Double实例,并将JChar Char构造函数添加到JValue,以及JSON Char的相应实例,我从ghci得到了预期的“不明确”响应。 所以我认为有一个bug。 评论?谢谢

    2 回复  |  直到 2 年前
        1
  •  4
  •   Ørjan Johansen    10 年前

    这不是一个bug,而是 ExtendedDefaultRules extension ,默认情况下在GHCi提示下启用,但不在文件中启用。

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

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

        2
  •  3
  •   user2407038    10 年前

    要了解实际情况:

    [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.