Say I have a map with measurable objects, and I'd like the maximum of their widths, defaulting to 0. The machinery of Foldable (foldMap) and Semigroup (Max) seems perfect, except that I can't seem to introduce the arbitrary lower bound.
data Thing
width :: Thing -> Double
maxWidth :: Map k Thing -> Double
maxWidth things = getMax . foldMap (Max . width) $ things
This rightly complains about the missing Bounded instance for Double, since the Monoid instance of Max a uses mempty = minBound.
I see that the source for Data.Foldable uses a different definition of newtype Max to implement maximum. That variant would do nicely, but it seems to not be exported:
maxWidth things = fromMaybe 0 . getMax . foldMap (Max . Just . width) $ things
You can use the
Optionmonoid to get a monoid instance for anySemigroup.Option ais just a newtype wrapper overMaybe a, but it'sMonoidinstance only requiresSemigroup arather thanMonoid a. So we can use it withMax:If you want a default value for the empty list case, you can use
fromMaybe:Another option is to just use
maximumMay :: (Ord a, Foldable t) => t a -> Maybe afrom thesafepackage.If you are using
base-4.11.0or higher, you no longer need theOption atype since the restriction onMonoid (Maybe a)has been lifted toSemigroup a. So as ofbase-4.11.0, which came with GHC 8.4.1, you can write: