A sample revised prelude for numeric classes
Marcin 'Qrczak' Kowalczyk
mk167280@students.mimuw.edu.pl
Mon, 12 Feb 2001 12:04:39 +0100 (CET)
On Mon, 12 Feb 2001, John Meacham wrote:
> My one request is that if at all possible, make some sort of partial
> ordering class part of the changes, they are just way to useful in all
> types of programs to not have a standard abstraction.
I like the idea of having e.g. (<) and (>) not necessarily total, and only
total compare. It doesn't need to introduce new operations, just split
an existing class into two.
Only I'm not sure why (<) and (>) should be partial, with (<=) and (>=)
total, and not for example opposite. Or perhaps all four partial, with
compare, min, max - total.
For partial ordering it's often easier to define (<=) or (>=) than (<) or
(>). They are related by (==) and not by negation, so it's not exactly the
same.
I would have PartialOrd with (<), (>), (<=), (>=), and Ord with the rest.
Or perhaps with names Ord and TotalOrd respectively?
There are several choices of default definitions of these four operators.
First of all they can be related either by (==) or by negation. The first
works for partial order, the second is more efficient in the case it works
(total order).
We can have (<=) and (>=) defined in terms of each other, with (<) and (>)
defined in terms of (<=) and (>=) - in either way. Or vice versa, but if
the definition is in terms of (==), then as I said it's better to let
programmers define (<=) or (>=) and derive (<), (>) from them. If they are
defined by negation, then we get more efficient total orders, but we must
explicitly define both one of (<=), (>=) and one of (<), (>) for truly
partial orders, or the results will be wrong.
Perhaps it's safer to have inefficient (<), (>) for total orders than
wrong for partial orders, even if it means that for optimal performance
of total orders one have to define (<=), (<) and (>):
class Eq a => PartialOrd a where -- or Ord
(<=), (>=), (<), (>) :: a -> a -> Bool
-- Minimal definition: (<=) or (>=)
a <= b = b >= a
a >= b = b <= a
a < b = a <= b && a /= b
a > b = a >= b && a /= b
We could also require to define one of (<=), (>=), and one of (<), (>),
for both partial and total orders. Everybody must think about whether he
defines (<) as negation of (>=) or not, and it's simpler for the common
case of total orders - two definitions are needed. The structure of
default definitions is more uniform:
class Eq a => PartialOrd a where -- or Ord
(<), (>), (<=), (>=) :: a -> a -> Bool
-- Minimal definition: (<) or (>), (<=) or (>=)
a < b = b > a
a > b = b < a
a <= b = b >= a
a >= b = b <= a
This is my bet.
--
Marcin 'Qrczak' Kowalczyk