A Haskell-ish takes over this question to notice that the following operations:
max, min :: Ord a => a -> a -> a max ab = if a < b then b else a min ab = if a < b then a else b
... associative :
max a (max bc) == max (max ab) c min a (min bc) == min (min ab) c
Thus, any type Ord a => a together with any of these operations is a semigroup , a concept for which reusable abstractions can be created.
And you are dealing with Maybe (Haskell for "option"), which adds a common "neutral" element to the base type a (you want max Nothing x == x executed as law). This will lead you to monoids , which are a subtype of semigroups.
The Haskell semigroups library provides a class of type Semigroup and two shell types, Max and Min , which generally implement the corresponding behavior.
Since we are dealing with Maybe , in terms of this library, the type that captures the semantics you want is Option (Max a) -a monoid, which has the same binary operation as the Max semigroup and uses Nothing as a single element. So the function just becomes:
maxOpt :: Ord a => Option (Max a) -> Option (Max a) -> Option (Max a) maxOpt ab = a <> b
... which, since it is just a <> operator for Option (Max a) , is not worth writing. You also get all the other utility functions and classes that work on Semigroup and Monoid , so for example, to find the maximum element [Option (Max a)] , you simply use the mconcat function .
The scalaz library comes with Semigroup and Monoid , as well as the Max , Min , MaxVal and MinVal tags that implement these features, so in fact the material that I demonstrated here in Haskell also exists in scalas.