
It seems to me that base is missing the very standard function `clamp :: Ord a => a -> a -> a -> a`:
```haskell clamp :: Ord a => a -> a -> a -> a clamp low high = min high .max low ```
I propose it be added to Data.Ord. It's useful, generic, and non-trivial to get right (the "big" number goes with "min" -- causes me cognitive dissonance every time.)
I'm -1 on the proposed type-signature. For one, while the motivation mentions cognitive overhead, it's ironic that the proposed :: Ord a => a -> a -> a -> a with three `a`-typed parameters whose grouping/semantics is all but obvious if you merely see the type-signature without knowing its implementation is itself a source of cognitive overhead IMO. On the other hand, there are already related functions taking lower/upper bounds defined by the Haskell Report, see https://www.haskell.org/onlinereport/haskell2010/haskellch19.html#x27-225000... and so it'd help to kill two birds with one stone by align the proposed `clamp` with the precedent established by the pre-existing functions in Data.Ix, such as ,---- | class Ord a => Ix a where | | range :: (a, a) -> [a] | The list of values in the subrange defined by a bounding pair. | | index :: (a, a) -> a -> Int | The position of a subscript in the subrange. | | inRange :: (a, a) -> a -> Bool | Returns True the given subscript lies in the range defined the bounding pair. | | rangeSize :: (a, a) -> Int | The size of the subrange defined by a bounding pair. `---- So by grouping the type-signature like clamp :: Ord a => (a,a) -> a -> a or even clamp :: Ord a => a -> (a,a) -> a it becomes a lot more obvious which parameters are the bounds and which is the subject it's operating upon and it's IMO less error-prone as there's now less risk to accidentally swap parameters around. Moreover, this turns `clamp` into a function taking two parameters, thereby allowing `clamp` to be used as infix operator (lower,upper) `clamp` x Having lower/upper bounds represented as tuple also makes it easier to define constants denoting the bounds, c.f. | ... = f (clamp int7Bounds x) ... | where | int7Bounds = (0,127) Long story short, I'm -1 on the proposed type-signature; I'm not against using a type-signature which groups the bounds-parameter into a tuple in alignment with the "Data.Ix" API. -- hvr