Early feedback: left-biasing `max`

I don’t know the original motivation, but I know plenty of cases when min / max returning something different from their arguments is useful.

  1. 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).

  1. Another case is that maybe min / max does 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
  1. Further, if evaluation of min / max requires some sort of normalisation of arguments, why would not we return the normalised value? For example, it makes a lot of sense for min (Add (Const 1) (Const 2)) (Const 5) to return Const 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.

1 Like