在Hashell中键入EQ怪异
学习如何在 haskell 中编写 typeClasses
一开始写了以下
data Trivial = ATrivial
instance Eq Trivial where
(==) trVal1 trVal2 = trVal1 == trVal2
并想知道它为什么有效?确实,以下表达式不应该编译,
trVal1 == trVal2
原因==onTrivial没有定义,充其量它应该无限期地递归。事实上,如果我对 Type 类的理解是正确的,那么 trVal1 和 trVal2 的唯一可能类型就是 Trivial。这受到 Type Class 的类型参数的约束Eq Trivial。
无论如何,即使我写这个,它仍然有效
data Trivial = ATrivial
instance Eq Trivial where
(==) trVal1 trVal2 = trVal1 :: Trivial == trVal2 :: Trivial
我相信写这个的正确方法是:
data Trivial = ATrivial
instance Eq Trivial where
(==) ATrivial ATrivial = True -- Using pattern matching
我是误解还是没有看到这里的东西?任何人都可以帮助消除歧义.....
编辑1
在 GHCI 中写入以下内容后
ATrivial == ATrivial
我什么也得不到?有没有办法让 REPL 抱怨而不是默默地杀死递归实际上不知道 REPL 在做什么
回答
它可以编译,因为通常具有递归定义是完全明智的,对于类实例也是如此。例如,Eq列表类型的实例看起来像
data List a = Nil | Cons a (List a)
instance (Eq a) => Eq (List a) where
Nil == Nil = True
Cons h t == Cons h' t' = h==h' && t==t'
_ == _ = False
这里,t==t'也是==对 on的“尚未定义”运算符的递归调用List a,但与您的示例不同,它使用减少的参数调用,因此如果使用有限列表调用,它将终止。
与 Agda 和 Coq 不同的是,Haskell 通常不会阻止您编写只会永远循环而没有进展的递归,同样与您是定义独立函数还是实例化类方法无关。