Opened 13 years ago

# Fix Ord so Ord Double and Ord Float make sense

Reported by: Owned by: Ian Lynagh none normal ⊥ discussion N/A or multiple

### Description

Consider:

```let n = 0/0 :: Double in (n `compare` n, n < n, n == n, n > n)
```

In GHC and YHC this gives

```(GT,False,False,False)
```

while in hugs it gives

```(EQ,False,False,False)
```

Neither of these is very satisfactory, as I would expect

```x `compare` y === EQ   =>   (x == y) === True
x `compare` y === GT   =>   (x > y) === True
```

and it's even less pleasant that the implementations differ for no good reason.

The Haskell report isn't currently very helpful on how comparing exceptional Doubles should behave, as it doesn't even say you need to have NaN etc:

```http://haskell.org/onlinereport/basic.html#sect6.4
The results of exceptional conditions (such as overflow or
underflow) on the fixed-precision numeric types are undefined; an
implementation may choose error (_|_, semantically), a truncated
value, or a special value such as infinity, indefinite, etc.
```

Four possible solutions to the problem have been proposed. While Haskell' would presumably continue not to legislate what implementations should do in this case, some of the solutions require changes to the report, so we do need to discuss it in the context of Haskell'.

The possible solutions are:

• `compare` should raise an exception (Haskell' doesn't need to be changed)
• `compare`, `(<)`, `(>)`, etc should raise an exception (Haskell' doesn't need to be changed)
• There should be no `Ord` instance for `Float` and `Double` (changes needed for Haskell')
• Add an `Incomparable` constructor to `Ordering` (changes needed for Haskell')

### comment:1 Changed 13 years ago by Ian Lynagh

```Another potentially attractive option is to recast Eq as being only a
PER (remove the reflexivity assumption) and allow Ord to be a partial
order.   Or maybe:

class PEq a where { (==) (/=) :: a -> a -> Bool }
class PEq a => Eq a

class POrd a where { compare :: ....; (<=) :: ...; etc }
class POrd a => Ord a

so we introduce new classes with the relaxed semantics and make Ord/
Eq subclasses with no new operations.
```

(still need to decide what `compare` should do in the POrd of Double)

### comment:2 Changed 13 years ago by Ian Lynagh

```I have another proposal: make different types.

People who want integers have the choice of Int (or Int64, etc) for performance
or Integer for stronger algebraic guarantees.

I suggest Double be split into types with different guarantees:
One that avoids "error" (and has weird NaN / Inf behavior)
Another that avoids having or propagating NaN/Inf by always throwing an error.
And perhaps an IEEE type with specific Nan/Inf behavior ?

So (0.0/0.0 :: Double) is NaN and (0.0/0.0 :: FiniteDouble) is an error.

The same applies to Float/FiniteFloat:

newtype FiniteDouble = FiniteDouble Double
newtype FiniteFloat = FiniteDouble Float
```

### comment:3 Changed 4 years ago by Herbert Valerio Riedel

Milestone: → ⊥

moving non-milestoned many year old legacy tickets out of the way

### comment:4 Changed 4 years ago by Herbert Valerio Riedel

Priority: major → normal

Set default priority (as this confuses Trac otherwise)

Note: See TracTickets for help on using tickets.