问题描述:

So I am playing around with Haskell and noticed something which puzzles me. I defined a complex floating point data structure and wanted to used comparison operators on it. Initally I did this which worked fine:

`data Cplx = Cplx Float Float deriving (Eq, Show)`

instance Ord Cplx where

(<=) a b = (<=) (normCplx a) (normCplx b)

(>=) a b = (>=) (normCplx a) (normCplx b)

(<) a b = (<) (normCplx a) (normCplx b)

(>) a b = (>) (normCplx a) (normCplx b)

normCplx :: Cplx -> Float

normCplx (Cplx a1 a2) = sqrt( a1^2 + a2^2)

But I also noticed just declaring:

`data Cplx = Cplx Float Float deriving (Eq, Show)`

instance Ord Cplx where

(<=) a b = (<=) (normCplx a) (normCplx b)

normCplx :: Cplx -> Float

normCplx (Cplx a1 a2) = sqrt( a1^2 + a2^2)

Also got the job done just fine. How does Haskell infer the definitons for the other comparison operators given only the single definition?

Thanks!

the rest is implemented just with the type-class using `(<=)`

(or `compare`

) - this is what "minimal implementation" in the docs here: http://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Ord mean.

Minimal complete definition: either compare or <=. Using compare can be more efficient for complex types.

Sadly in this case you cannot show the source directly from Hackage but as `Ord a`

implies `Eq a`

it's not hard to imagine how this is done.

For example as you have `(<=)`

implemented `(<)`

can just be:

```
a < b = a /= b && a <= b
```

with that you get

```
a >= b = not (a < b)
```

and finaly

```
a > b = not (a <= b)
```

or something similar.

Btw as you might have seen in your first implementation you did not implement `compare`

, `max`

or `min`

even if it's part of the type-class and this it got infered too.

Maybe you can try to guess it yourself.

David found the sources - here is the implementation right from there:

```
class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>), (>=) :: a -> a -> Bool
max, min :: a -> a -> a
compare x y = if x == y then EQ
-- NB: must be '<=' not '<' to validate the
-- above claim about the minimal things that
-- can be defined for an instance of Ord:
else if x <= y then LT
else GT
x < y = case compare x y of { LT -> True; _ -> False }
x <= y = case compare x y of { GT -> False; _ -> True }
x > y = case compare x y of { GT -> True; _ -> False }
x >= y = case compare x y of { LT -> False; _ -> True }
-- These two default methods use '<=' rather than 'compare'
-- because the latter is often more expensive
max x y = if x <= y then y else x
min x y = if x <= y then x else y
{-# MINIMAL compare | (<=) #-}
```

As you can see: if you have `compare`

or `(<=)`

all else follows.

It must be said that the `Ord`

typeclass is for types with *total order*, and complex numbers do not satisfy the properties of total order. In particular, your implementation violates the *anti-symmetry* property, that is,

```
forall a b. if a ≤ b and b ≤ a then a = b.
```

Failing to satisfy this property violates the contract of `Ord`

and could result in strange bugs, depending on how the instance is used.

It might be more appropriate to apply `normCplx`

where you might have relied on functionality derived from `Ord`

, e.g., `sortBy (compare `on` normCplx)`

where you might have just used `sort`

.