简体   繁体   中英

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

I am quite new to Haskell/Purescript and currently learning by studying the PureScript by Example book .

In chapter 6 about type classes, exercise 4 has following task:

(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 .

Here is my attempt:
 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

Unfortunately, the code triggers an error:

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)

I cannot quite understand the error message:

  1. What does expression #dict Eq mean? There is no dict in my code.
  2. What is a rigid type variable?
  3. The error seems to use different identifiers like a0 (why? I assume, that is a )

In my book, Eq type class instance should be covered by implementing Ord , as Ord extends Eq .

The key part of the error is at the start:

No type class instance was found for

    Data.Eq.Eq (Extended a0)

Here is the definition of Ord :

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

This is actually the superclass syntax, saying that you need an Eq instance to have an Ord instance. So, you can fix the error by making an Eq instance:

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

As to why a0 is used, it seems the purescript compiler just likes adding numbers after type variables, possibly to reduce vagueness or to allow for scoped type variables. You can read about rigid type variables here (they're basically variables that can't be changed to fit constraints).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM