0

学习如何在 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 在做什么

4

1 回答 1

5

它可以编译,因为通常具有递归定义是完全明智的,对于类实例也是如此。例如,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'也是对“尚未定义”==运算符的递归调用List a,但与您的示例不同,它使用减少的参数调用,因此如果使用有限列表调用,它将终止。

与 Agda 和 Coq 不同,Haskell 通常不会阻止您编写只会永远循环而没有进展的递归,这与您是定义独立函数还是实例化类方法无关。

于 2021-01-05T15:45:59.247 回答