这真的很简单。让我们问一下 GHCi 的类型isList2
是什么:
∀x. x ⊢ :t isList2
isList2 :: a -> Bool
这与实例不匹配[a]
(即使它可以通过统一),但它确实a
立即匹配实例。因此,GHC 选择a
实例,因此isList2
返回False
.
这种行为恰恰是什么IncoherentInstances
意思。实际上,这是一个很好的演示。
有趣的是,如果你简单地禁用IncoherentInstances
,我们会得到完全相反的效果,GHCi 现在这样说:
∀x. x ⊢ :t isList2
isList2 :: [Integer] -> Bool
发生这种情况isList2
是因为顶层绑定没有使用函数语法定义,因此受到 Dreaded Monomorphism Restriction 的约束。所以它被专门用于它实际使用的实例。
添加NoMonomorphismRestriction
和禁用IncoherentInstances
,我们得到了这个:
∀x. x ⊢ :t isList2
isList2 :: IsList a => a -> Bool
∀x. x ⊢ isList2 'a'
False
∀x. x ⊢ isList2 "a"
True
∀x. x ⊢ isList2 undefined
<interactive>:19:1:
Overlapping instances for IsList a0 arising from a use of `isList2'
这是预期的重叠行为,如果选择不明确,则根据使用和投诉选择实例。
关于对问题的编辑,我不相信没有类型注释就可以获得所需的结果。
第一个选项是提供isList2
类型签名,以防止IncoherentInstances
过早选择实例。
isList2 :: (IsList a) => a -> Bool
isList2 = isList
您可能需要在其他任何isList
提到(甚至是间接)的地方做同样的事情,而不是应用于一个论点。
第二个选项是消除数字文字的歧义并禁用IncoherentInstances
.
main =
print (isList (42 :: Integer)) >>
print (isList2 (42 :: Integer)) >>
print (isList [42]) >>
print (isList2 [42])
在这种情况下,有足够的信息来选择一个最具体的实例,OverlappingInstances
它的事情也是如此。