Reputation: 35
maxs :: (RealFloat a) => a -> a -> a
maxs a b
| a>b = a
| otherwise = b
maxs :: (Ord a) => a -> a -> a
maxs a b
| a>b = a
| otherwise = b
I'm trying to write a max function using Haskell. These two seem to work both. I wrote the first one and the latter one comes from the book. My question is, what's the difference between them? Can they replace each other?
The ord class is used for totally ordered datatypes. But in this case, order doesn't seem to matter.
Upvotes: 1
Views: 87
Reputation: 62848
RealFloat
implies RealFrac
which implies Real
which in turn implies Ord
.
In other words, every type that is an instance of RealFloat
must also be an instance of Ord
. So both of these functions require Ord
(which is what defines the "<
" operator that you're trying to use). But the first one pointlessly also requires a bunch of stuff to do with floating-point numbers (e.g., the cos
function).
Order most certainly does matter; that's the whole point of a max function. It's to find the maximum value. Without an ordering, there is no maximum value!
By using RealFrac
, on the other hand, you are prevented from (for example) finding the maximum String
, since a String
clearly isn't any kind of floating-point number.
Upvotes: 1
Reputation: 2477
Suppose I write two functions:
f :: (a, b) -> a
f (x, y) = x
g :: (Int, Bool) -> Int
g (x, y) = x
What is the difference? Function g
is less general because its type is more precise than the type of f
. In a sense g
is "artificially restricted" to work only on (Int, Bool)
when it could work on any product type.
The situation with your two definitions of $\max$ is similar. One is more general than the other, but not because it does anything smarter, but because you declared one of them to work on any Ord
instance, while the other works only on the RealFloat
instances.
By the way, Ord
is more or less unavoidable here because if you have max
you can define $\leq$ by
$$x \leq y \iff \max(x,y) = y.$$
Upvotes: 4