在Haskell中重叠实例

Jam*_*Lee 9 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")]
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*her 19

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

这是一个误解.GHC执行实例选择仅考虑实例头,而不考虑实例的任何约束.

instance (JSON a) => JSON [a] where
Run Code Online (Sandbox Code Playgroud)

用于实例选择的目的与...相同

instance JSON [a] where
Run Code Online (Sandbox Code Playgroud)

也是的背景

instance (JSON a) => JSON [(String, a)] where
Run Code Online (Sandbox Code Playgroud)

被忽略的实例选择.

因此,GHC看到了这两个例子

instance JSON [a]
instance JSON [(String, a)]
Run Code Online (Sandbox Code Playgroud)

他们都符合要求

instance JSON [(String, String)]
Run Code Online (Sandbox Code Playgroud)

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

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


J. *_*son 6

这些存在

ghci> :i ToJSON
...
instance ToJSON [Char]
...
instance (ToJSON a, ToJSON b) => ToJSON (a, b)
Run Code Online (Sandbox Code Playgroud)

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