gpt4 book ai didi

Haskell 重叠/不连贯的实例

转载 作者:行者123 更新时间:2023-12-04 00:50:25 25 4
gpt4 key购买 nike

我知道这是代码有点傻,但有人可以解释为什么 isList [42]返回 TrueisList2 [42]打印 False ,以及如何防止这种情况?我想更好地理解一些更晦涩的 GHC 类型扩展,我认为这将是一个有趣的例子。

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE IncoherentInstances #-}

class IsList a where
isList :: a -> Bool

instance IsList a where
isList x = False

instance IsList [a] where
isList x = True

isList2 = isList

main =
print (isList 42) >>
print (isList2 42) >>
print (isList [42]) >>
print (isList2 [42])

最佳答案

这真的很简单。请问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是一个没有使用函数语法定义的顶级绑定(bind),因此受到可怕的单态限制。所以它被专门用于它实际使用的实例。

添加 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做它的事。

关于Haskell 重叠/不连贯的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16050566/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com