Ord:未找到 Data.Eq.Eq 类型的 class 实例(扩展 a0)。 PureScript by Example 书,第 6 章

Ord: No type class instance was found for Data.Eq.Eq (Extended a0). PureScript by Example book, Chapter 6

我对 Haskell/Purescript 很陌生,目前正在学习 PureScript by Example book

chapter 6 about type classes, exercise 4 中有以下任务:

(Medium) Given any type a with an instance of Ord, we can add a new "infinite" value which is greater than any other value:

data Extended a = Finite a | Infinite

Write an Ord instance for Extended a which reuses the Ord instance for a.

这是我的尝试:
instance ordExtended :: Ord a => Ord (Extended a) where
  compare Infinite Infinite = EQ
  compare Infinite _ = GT
  compare _ Infinite = LT
  compare (Finite f1) (Finite f2) = compare f1 f2

不幸的是,代码触发了一个错误:

No type class instance was found for

Data.Eq.Eq (Extended a0)

while checking that expression #dict Eq has type { eq :: Extended a0 -> Extended a0 -> Boolean } in value declaration ordExtended

where a0 is a rigid type variable bound at (line 0, column 0 - line 0, column 0) PureScript(NoInstanceFound)

我不太明白错误信息:

  1. expression #dict Eq 是什么意思?我的代码里没有dict.
  2. 什么是刚性类型变量?
  3. 错误似乎使用了不同的标识符,例如 a0(为什么?我假设是 a

在我的书中,Eq 类型 class 实例应该通过实现 Ord 来涵盖,因为 Ord 扩展了 Eq.

错误的关键部分在开头:

No type class instance was found for

    Data.Eq.Eq (Extended a0)

这里是Ord的定义:

class Eq a <= Ord a where
  compare :: a -> a -> Ordering

这实际上是superclass语法,说你需要一个Eq实例才能有一个Ord实例。因此,您可以通过创建 Eq 实例来修复错误:

instance eqExtended :: Eq a => Eq (Extended a) where
  eq Infinite Infinite = true
  eq (Finite f1) (Finite f2) = eq f1 f2
  eq _ _ = false

instance ordExtended :: Ord a => Ord (Extended a) where
  compare Infinite Infinite = EQ
  compare Infinite _ = GT
  compare _ Infinite = LT
  compare (Finite f1) (Finite f2) = compare f1 f2

至于为什么使用 a0,似乎纯脚本编译器只是喜欢在类型变量之后添加数字,可能是为了减少模糊性或允许作用域类型变量。您可以 read about rigid type variables here(它们基本上是无法更改以适应约束的变量)。