I don’t know the original motivation, but I know plenty of cases when min / max returning something different from their arguments is useful.
- Quite often the difference between semantical and structural equality is in some sort of annotation with a provenance / position. E. g.,
data Value = Value { getValue :: Int, getProvenance :: Position }
instance Eq Value where
(==) = (==) `on` getValue
Now what is the provenance of min x y :: Value? It might be sensible to set Position to <no location>, or maybe to a position of min itself, or maybe combine position ranges somehow. In all these cases min x y is structurally neither x nor y (but semantically equal to one of them).
- Another case is that maybe
min/maxdoes not evaluate anything, but just construct a correspondent expression. Say,
data Expr
= Const Int
| Add Expr Expr
| Mul Expr Expr
| Min Expr Expr
| Max Expr Expr
and then simply
min :: Expr -> Expr -> Expr
min = Min
- Further, if evaluation of
min/maxrequires some sort of normalisation of arguments, why would not we return the normalised value? For example, it makes a lot of sense formin (Add (Const 1) (Const 2)) (Const 5)to returnConst 3.
A variation of above is the following definition of min for ByteString:
min x y
| Data.ByteString.null x = mempty
| otherwise = ...
Even while x == mempty, it is not necessarily structurally equal to it (it might be a zero slice of a larger ByteString). And yet this is a sensible definition, useful to free up some over-retained data.