【问题标题】:Haskell functional dependency a b -> c depending on c?Haskell 函数依赖 a b -> c 取决于 c?
【发布时间】:2023-03-26 18:14:01
【问题描述】:

考虑以下 Haskell 代码:

{-# 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 是的,它只取决于最后两个实例
  • 我无法在这里复制第二部分。 instance C (l i j) (r i j) i 给我带来了冲突。 (在 ghc 7.8.3 上)
  • @genisage 这里没有冲突,还有 ghc(i) 7.8.3
  • @ØrjanJohansen 我又试了一次,还是有冲突。我目前正在使用 windows 和 Haskell 平台。

标签: haskell functional-dependencies type-families


【解决方案1】:

最后两个实例有冲突的统一。让我使用完全不同的变量名:

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:确实,如果我尝试编写一个类方法f :: a -> b -> c,我会在调用f时收到关于不连贯的投诉
猜你喜欢
  • 2015-08-08
  • 1970-01-01
  • 2020-12-25
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多