在Haskell中重叠实例

时间:2013-05-27 15:18:17

标签: haskell typeclass

阅读本书Real world Haskell下面的重叠实例示例

instance (JSON a) => JSON [a] where
    toJValue = undefined
    fromJValue = undefined

instance (JSON a) => JSON [(String, a)] where
    toJValue = undefined
    fromJValue = undefined

ghci> toJValue [("foo","bar")]

<interactive>:1:0:
    Overlapping instances for JSON [([Char], [Char])]
      arising from a use of `toJValue' at <interactive>:1:0-23
Matching instances:
  instance (JSON a) => JSON [a]
    -- Defined at BrokenClass.hs:(44,0)-(46,25)
  instance (JSON a) => JSON [(String, a)]
    -- Defined at BrokenClass.hs:(50,0)-(52,25)
   In the expression: toJValue [("foo", "bar")]
   In the definition of `it': it = toJValue [("foo", "bar")]

根据我的理解,这不会是重叠,因为[a]不应该是一个选择,因为对JSON [a]的限制是'a'必须是JSON的实例本身。 (String,a)没有JSON实例。

2 个答案:

答案 0 :(得分:19)

  

根据我的理解,这不会是重叠,因为[a]不应该是一个选择,因为对JSON [a]的限制是a必须是实例本身是JSONJSON没有(String, a)的实例。

这是一种误解。 GHC执行实例选择只考虑实例头,而不考虑实例的任何约束。

instance (JSON a) => JSON [a] where

表示实例选择的目的与

相同
instance JSON [a] where

也是

的背景
instance (JSON a) => JSON [(String, a)] where
实例选择会忽略

因此GHC看到了两个实例

instance JSON [a]
instance JSON [(String, a)]

并且它们都匹配所需的

instance JSON [(String, String)]

这意味着你有重叠(无论实际存在什么实例以及这两个实例中的每个实例有什么限制)。

如果选择了实例,则会考虑约束,如果不满足,则为类型错误。

答案 1 :(得分:6)

这些存在

ghci> :i ToJSON
...
instance ToJSON [Char]
...
instance (ToJSON a, ToJSON b) => ToJSON (a, b)

即使GHC考虑了背景,也会有重叠(参见Daniel Fischer的回答)。