为什么类型类覆盖条件在 Haskell 中失败,但在 PureScript 中却失败

tom*_*tom 4 haskell purescript

我有两个我认为等效的类型类和实例定义的实现。PureScript 版本构建时没有错误,但 Haskell 版本失败并出现错误Un-determined variables: e, f

我可以在 Haskell 中完成这个工作吗?

哈斯克尔:

class Foo a b c | a b -> c where
newtype Bar a b = Bar (a, b)
instance (Foo a c e, Foo b d f) => Foo (Bar a b) (Bar c d) (Bar e f) where
Run Code Online (Sandbox Code Playgroud)

纯脚本:

class Foo a b c | a b -> c
newtype Bar a b = Bar (Tuple a b)
instance (Foo a c e, Foo b d f) => Foo (Bar a b) (Bar c d) (Bar e f) 
Run Code Online (Sandbox Code Playgroud)

Dan*_*ner 8

您必须启用UndecidableInstances;那么你的声明就会起作用。为什么需要这样做有点微妙,即启用它会如何导致类型检查器中的循环。但是假设在您的程序中,您以某种方式导致需要解决以下约束:

Foo (Bar a b) (Bar c d) a
Run Code Online (Sandbox Code Playgroud)

约束求解器会很高兴地观察到我们必须选择您编写的实例,并决定因此a ~ Bar a0 a1对于某些a0a1,这意味着我们想要求解约束:

Foo (Bar (Bar a0 a1) b) (Bar c d) (Bar a0 a1)
Run Code Online (Sandbox Code Playgroud)

现在我们可以调度到上下文,这意味着我们现在需要解决以下两个约束:

( Foo (Bar a0 a1) c a0
, Foo b d a1
)
Run Code Online (Sandbox Code Playgroud)

可是等等!第一个约束与我们开始时的约束具有相同的形式,但具有不同的类型变量。一个循环!

  • PureScript 的工作方式确实与“UndecidableInstances”类似。在 Haskell 中,启用 UI 后,终止检查将推迟到使用站点,此时尝试解决循环约束将产生错误“_Reduction stack Overflow_”。在 PureScript 中,相同的尝试会导致错误“_(blah) 的类型类实例可能是无限的_”。我必须承认,我不确定 PS 编译器如何确定这一点:它是否只是尝试看看它是否循环足够长的时间(就像 GHC 那样)或者有更聪明的方法。 (2认同)