Haskell/GHC不可判定实例-非终止类型检查示例?

Haskell/GHC不可判定实例-非终止类型检查示例?,haskell,ghc,typechecking,decidable,Haskell,Ghc,Typechecking,Decidable,我编写了一些Haskell代码,需要编译-XUndecidableInstances。我确实理解为什么会发生这种情况,因为有一个特定的条件被违反,因此GHC大喊大叫 然而,我从来没有遇到过这样的情况,类型检查器实际上会挂起或陷入一个无休止的循环 非终止实例定义是什么样的-您能举个例子吗?例如: {-# LANGUAGE UndecidableInstances #-} class C a where f :: a -> a instance C [[a]] => C [a

我编写了一些Haskell代码,需要编译-XUndecidableInstances。我确实理解为什么会发生这种情况,因为有一个特定的条件被违反,因此GHC大喊大叫

然而,我从来没有遇到过这样的情况,类型检查器实际上会挂起或陷入一个无休止的循环

非终止实例定义是什么样的-您能举个例子吗?

例如:

{-# LANGUAGE UndecidableInstances #-}

class C a where
    f :: a -> a

instance C [[a]] => C [a] where
    f = id

g x = x + f [x]
发生的情况:当键入
f[x]
时,编译器需要确保
x::C[a]
对于某些
a
。实例声明指出,
x
只能是
C[a]
类型,前提是它也是
C[[a]]
。因此,编译器需要确保
x::C[[a]]
等,并在无限循环中捕获


另请参见

在以下内容中有一个经典的、有点令人担忧的示例(涉及与函数依赖项的交互):

我们需要
mul x[y]
具有与
y
相同的类型,因此,采用
x::x
y::y
,我们需要

instance Mul x [y] y
根据给定的实例,我们可以得到。当然,对于某些
z
,我们必须取
y~[z]
,以便

instance Mul x y z
i、 e

我们在一个循环中

这是令人不安的,因为
Mul
实例看起来像是它的递归在结构上减少了,这与Petr答案中明显病态的实例不同。然而,它使GHC循环(无聊的门槛踢进来,以避免挂起)

问题是,我肯定我在什么时候提到过,尽管
z
在功能上依赖于
y
,但识别
y~[z]
还是存在的。如果我们对函数依赖项使用函数表示法,我们可能会看到约束显示为
y~Mul x[y]
,并拒绝替换,因为它违反了发生检查

我很好奇,我想我应该试一试

class Mul' a b where
  type MulT a b
  mul' :: a -> b -> MulT a b

instance Mul' a b => Mul' a [b] where
  type MulT a [b] = [MulT a b]
  mul' a = map (mul' a)

g b x y = if b then mul' x [y] else y
启用了
UndedicatableInstances
后,循环需要很长时间才能超时。禁用
UndedicatableInstances
后,实例仍被接受,typechecker仍在循环,但截断发生得更快


所以。。。有趣的旧世界。

回答得很好,谢谢!我接受了Petr的回答,因为它不涉及对类型系统的额外扩展。不用担心!当我们在一般地区时,我只是想提高人们对一个已知的小精灵的认识。谢谢你的提问!
instance Mul x [z] z
class Mul' a b where
  type MulT a b
  mul' :: a -> b -> MulT a b

instance Mul' a b => Mul' a [b] where
  type MulT a [b] = [MulT a b]
  mul' a = map (mul' a)

g b x y = if b then mul' x [y] else y