Haskell函数依赖a b -> c是否取决于c?

6
请问需要翻译的内容是什么?
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances,
    FunctionalDependencies #-}

class C a b c | a b -> c

instance C (l (i,j)) (r i j)   j
instance C (l i j)   (r (i,j)) j
-- Conflict between the following two lines
instance C (l (i,j)) (r (i,j)) j  
instance C (l i j)   (r i j)   j

在这里,GHC在最后两行之间产生了一个功能依赖错误。如果我删除最后两个实例声明中的任何一个,代码就可以编译。我尝试使用类型族进行类比,但也产生了冲突。我的第一个问题是:为什么最后两行会发生冲突,而其他声明都可以一起正常工作?

此外,如果我将最后一行更改为

instance C (l i j)   (r i j)   i

GHC接受了这段代码。这似乎很奇怪,因为唯一改变的是依赖类型变量c。有人能解释一下这种行为吗?


只是为了确保。 如果您删除前两个实例中的两个,仍然会出现错误,对吗? - genisage
@genisage 是的,它只取决于最后两个实例。 - Nicolas Malebranche
我无法在此处重现第二部分。instance C (l i j) (r i j) i 对我造成了冲突。(在 GHC 7.8.3 上) - genisage
@genisage 这里没有冲突,同时支持 ghc(i) 7.8.3。 - Ørjan Johansen
@genisage 我也是!好奇... - Ørjan Johansen
显示剩余3条评论
1个回答

6
最后两个实例存在冲突的统一。让我使用完全不同的变量名:
C (a c (d,e)) (b c (d,e)) e
vs.
C (a c (d,e)) (b c (d,e)) (d,e)

特别是,你第三个实例中的l可以统一到一个已经有参数应用的类型构造器中。

将你的j改为i,则变为最后一个:

C (a c (d,e)) (b c (d,e)) c

我仍然不明白为什么这不会引发投诉。也许是因为您可以分配类型,例如 c = e,但不能分配类型e = (d,e)(这将导致Haskell不允许的无限类型),但仍然似乎是一件值得怀疑的事情。也许这甚至是GHC的一个错误。
其他实例组合不会冲突,因为当您尝试统一它们时,您会遇到类似于上面的e =(d,e)的矛盾,但在非依赖部分,所以它们无法匹配。

我同意你的观点。在实验过程中,我发现 class C a b ; instance C (l (i,j)) (r (i,j)) ; instance C (l i j) (r i j) 被接受了,而没有提到重叠的问题(?)。也许现在一些重叠只有在调用方法时才被检测到(这只是猜测)。 - chi
感谢您指出统一过程。@chi:确实,如果我尝试编写一个类方法f :: a -> b -> c,当调用f时会收到不一致的投诉。 - Nicolas Malebranche

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接