Safe `maximum` in Haskell Standard Library? - haskell

Is there a safe equivalent of maximum in Haskell's Standard Library?
*Main Control.Monad.State Data.List> maximum []
*** Exception: Prelude.maximum: empty list
I tried to find one, (Ord a, Foldable t) => t a -> Maybe a with hoogle, but found none.

For the sake of completeness: loosening your "Standard Library" requirement to "some very commonly used library", the safe package provides the Safe.Foldable module, which includes a maximumMay function:
maximumMay :: (Foldable t, Ord a) => t a -> Maybe a

You can code one up yourself for any Foldable, by applying foldMap to a suitable choice of Monoid.
The Option monoid takes an existing Semigroup and lifts it into a Monoid by adjoining an empty element (Option Nothing), which'll be returned by foldMap if the input Foldable is empty. The Max newtype lifts any instance of Ord into a Semigroup by making <> pick the larger of its arguments.
So by foldMapping the input Foldable through the composition of Option and Max, we get your desired behaviour.
safeMaximum :: (Foldable t, Ord a) => t a -> Maybe a
safeMaximum = fmap getMax . getOption . foldMap (Option . Just . Max)
ghci> safeMaximum "wowzers"
Just 'z'
ghci> safeMaximum ""
Nothing

You could create your own:
maximumMaybe :: (Ord a, Foldable f) => f a -> Maybe a
maximumMaybe xs
| null xs = Nothing
| otherwise = Just $ maximum xs
Previous Answer (not foldable):
maximumMaybe :: Ord a => [a] -> Maybe a
maximumMaybe xs = listToMaybe xs *> Just (maximum xs)
Or if you like point-free style:
maximumMaybe :: Ord a => [a] -> Maybe a
maximumMaybe = (<*) . Just . maximum <*> listToMaybe
Another, simpler, solution is:
maximumMaybe :: Ord a => [a] -> Maybe a
maximumMaybe [] = Nothing
maximumMaybe xs = Just $ maximum xs

Related

What does Traversable is to Applicative contexts mean?

I am trying to understand Traversable with the help of https://namc.in/2018-02-05-foldables-traversals.
Somewhere the author mentioned the following sentence:
Traversable is to Applicative contexts what Foldable is to Monoid
values.
What did he try to clarify?
I do not get the connection between Foldable to Monoid.
Please provide an example.
In the beginning, there was foldr:
foldr :: (a -> b -> b) -> b -> [a] -> b
and there was mapM:
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
foldr was generalized to data types other than [a] by letting each type define its own definition of foldr to describe how to reduce it to a single value.
-- old foldr :: (a -> b -> b) -> b -> [] a -> b
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
If you have a monoid, you don't have to specify a binary function, because the Monoid instance already provides its own starting value and knows how to combine two values, which is apparent from its default definition in terms of foldr:
-- If m is a monoid, it provides its own function of type b -> b.
foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
foldMap f = foldr (mappend . f) mempty
Traverse does the same kind of generalization from lists to traversable types, but for mapM:
-- old mapM :: Monad m => (a -> m b) -> [] a -> m ([] b)
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
(When mapM was first defined, there was no Applicative class; if there had been, mapA :: Applicative f => (a -> f b) -> [a] -> f [b] could have been defined instead; the Monad constraint was stronger than was necessary.)
An Applicative is monoidal in nature, so there was no need in Traverse for the type of distinction that foldr/foldMap draws.
The article (and the corresponding passage of the Wikibook) is talking about how the effects (or, to use the language seen there, the contexts) of applicative values can be combined monoidally. The connection with Foldable is that list-like folding is ultimately amounts to combining values monoidally (see chepner's answer, and also Foldr/Foldl for free when Tree is implementing Foldable foldmap?. As for the applicative contexts part, there are a few ways to look at that. One of them is noting that, for any Applicative f and Monoid m, f m is a monoid, with pure mempty as mempty and liftA2 mappend as mappend (this Ap type from the reducers package witnesses that). For a concrete example, let's pick f ~ Maybe and m ~ (). That leaves us with four possible combinations:
liftA2 mappend (Just ()) (Just ()) = Just ()
liftA2 mappend (Just ()) Nothing = Nothing
liftA2 mappend Nothing (Just ()) = Nothing
liftA2 mappend Nothing Nothing = Nothing
Now contrast with All, the Bool monoid with (&&) as mappend:
mappend (All True) (All True) = All True
mappend (All True) (All False) = All False
mappend (All False) (All True) = All False
mappend (All False) (All False) = All False
They match perfectly: Just () stands for True, Nothing for False, and liftA2 mappend for (&&).
Now let's have another look at the Wikibook example:
deleteIfNegative :: (Num a, Ord a) => a -> Maybe a
deleteIfNegative x = if x < 0 then Nothing else Just x
rejectWithNegatives :: (Num a, Ord a, Traversable t) => t a -> Maybe (t a)
rejectWithNegatives = traverse deleteIfNegative
GHCi> rejectWithNegatives [2,4,8]
Just [2,4,8]
GHCi> rejectWithNegatives [2,-4,8]
Nothing
The Maybe values generated by applying deleteIfNegative to the values in the lists are combined monoidally in the way shown above, so that we get a Nothing unless all the Maybe values are Just.
This matter can also be approached in the opposite direction. Through the Applicative instance for Const...
-- I have suppressed a few implementation details from the instance used by GHC.
instance Monoid m => Applicative (Const m) where
pure _ = Const mempty
Const x <*> Const y = Const (x `mappend` y)
... we can get an Applicative out of any Monoid, such that (<*>) combines the monoidal values monoidally. That makes it possible to define foldMap and friends in terms of traverse.
On a final note, the category theoretical description of Applicative as a class for monoidal functors involves something rather different from what I have covered here. For further discussion of this issue, and of other fine print, see Monoidal Functor is Applicative but where is the Monoid typeclass in the definition of Applicative? (if you want to dig deeper, it is well worth it to read all of the answers there).

How to eliminate the boilerplate of wrapping and unwrapping using lenses

tl;dr: is it possible to use any of the lens family of abstractions to wrap/unwrap any arbitrary newtype (that provides an instance for such abstractions)?
I'll motivate my question by a simple example, based on a true story. Suppose I define the following newtype:
newtype FreeMonoid a = FreeMonoid { asMap :: Map a Int }
which is used to represent terms of the form:
a0 <> a1 <> ... <> an-1
We can represent free-monoids as lists:
instance Ord a => IsList (FreeMonoid a) where
type Item (FreeMonoid a) = a
fromList xs = FreeMonoid $ Map.fromListWith (+) $ zip xs (repeat 1)
toList (FreeMonoid p) = do
(x, n) <- Map.toList p
genericReplicate n x
Two examples of free-monoids are sequences of sum and sequences of products:
type FreeSum a = FreeMonoid (Sum a)
type FreeProduct a = FreeMonoid (Product a)
Where Sum and Product are defined in Data.Monoid. Now we could define fromList and toList operations for FreeSum and
FreeProduct as follows:
fromListSum :: Ord a => [a] -> FreeSum a
fromListSum = fromList . (Sum <$>)
fromListProduct :: Ord a => [a] -> FreeProduct a
fromListProduct = fromList . (Product <$>)
But this has quite a lot of boilerplate. It'd be nicer if we could simply say:
fromListW :: (Ord a, Wrapper f) => [a] -> FreeMonoid (f a)
fromListW = fromList . (wrap <$>)
where wrap is some operation of the (hypotetical) Wrapper class were:
wrap :: a -> f a
unwrap :: f a -> a
Similarly, I'd like to be able to write a function:
toListW :: (Ord a, Wrapper f) => FreeMonoid (f a) -> [a]
toListW = (unwrap <$>) . toList
Lenses seem to provide such an abstraction in Control.Lens.Wrapped (for which Sum and Product in this example are instances of the typeclasses there!). However my attempts to understand and use the abstractions in this module have failed. For instance:
fromListW :: (Ord a, Wrapped (f a)) => [a] -> FreeMonoid (f a)
fromListW = fromList . (Wrapped <$>)
won't work since the argument is not a list of Unwrapped (f a).
So my question is:
Do lenses provide an abstraction similar to this Wrapper class?
If not, can this "scrap-your-boilerplate" problem be solved by using lenses?
The "problem" is that you're using Wrapped, which is really meant to be a convenience pattern synonym and not a wrapping "constructor". Because it's designed to support polymorphic wrapping, you need to assert that your type can be rewrapped:
fromListW :: (Rewrapped a a, Ord a) => [Unwrapped a] -> FreeMonoid a
fromListW = fromList . (Wrapped <$>)
This then works as expected:
> let x = [1,2,3]
> fromListW x :: FreeMonoid (Sum Int)
FreeMonoid {asMap = fromList [(Sum {getSum = 1},...
> fromListW x :: FreeMonoid (Product Int)
FreeMonoid {asMap = fromList [(Product {getProduct = 1},...
>
I think a more idiomatic lens implementation would be:
fromListW :: (Rewrapped a a, Ord a) => [Unwrapped a] -> FreeMonoid a
fromListW = fromList . view (mapping _Unwrapped)
This still requires the Rewrapped a a constraint, but you can use the non-polymorphic _Unwrapped' instead:
fromListW :: (Wrapped a, Ord a) => [Unwrapped a] -> FreeMonoid a
fromListW = fromList . view (mapping _Unwrapped')
which looks a little more natural.
The toListW implementation would have similar structure:
toListW :: (Wrapped a, Ord a) => FreeMonoid a -> [Unwrapped a]
toListW = view (mapping _Wrapped') . toList

Restricting type parameter to Monoid

I've previously defined a function which takes a list of Maybes and turns it into a Maybe of a list, like so:
floop :: [Maybe a] -> Maybe [a]
floop [] = Just []
floop (Nothing:_) = Nothing
floop (Just x:xs) = fmap (x:) $ floop xs
Now I want to redefine it to be compatible with a larger class of containers, not just lists, and I've found that it needs to implement the functions foldr, mappend, mempty, fmap , and pure; so I figure that the following type line would be appropriate:
floop :: (Foldable t, Functor t, Monoid t) => t (Maybe a) -> Maybe (t a)
As (I think) it ensures that those functions are implemented for the given container, however it leads to the following error:
Expecting one more argument to ‘t’
The first argument of ‘Monoid’ should have kind ‘*’,
but ‘t’ has kind ‘* -> *’
In the type signature for ‘floop'’:
floop' :: (Foldable t, Functor t, Monoid t) =>
t (Maybe a) -> Maybe (t a)
After looking into it, I found Monoid's kind is different to that of Functor and Foldable, but I can't see why that would be the case, nor how to correct the error.
For those interested, here's the current implementation:
floop :: (Foldable t, Functor t, Monoid t) => t (Maybe a) -> Maybe (t a)
floop xs = let
f :: (Foldable t, Functor t, Monoid t) => Maybe a -> Maybe (t a) -> Maybe (t a)
f Nothing _ = Nothing
f (Just x) ys = fmap (mappend $ pure x) ys
in
foldr f (Just mempty) xs
Note: I have been made aware that this already exists as a builtin function (sequence), but I intend to implement it as a learning exercise.
Monoidal applicatives are described by the Alternative class, using (<|>) and empty instead of mappend and mempty:
floop :: (Foldable t, Alternative t) => t (Maybe a) -> Maybe (t a)
floop xs = let
f :: (Foldable t, Alternative t) => Maybe a -> Maybe (t a) -> Maybe (t a)
f Nothing _ = Nothing
f (Just x) ys = fmap ((<|>) $ pure x) ys
in
foldr f (Just empty) xs
This might be a good place to bring up hoogle.
Searching for t (m a)-> m (t a) returns sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a) as the first result. This then leads to the Traversable type class which is fairly close to what you are looking for.
As Lee said you could use the Alternative class which is the Applicative equivalent of Monoid. Slightly more generalized:
sequence' :: (Alternative t, Foldable t, Applicative a) => t (a b) -> a (t b)
sequence' = foldr step (pure empty)
where step = liftA2 prepend
prepend = (<|>) . pure
Here prepend first wraps some single element into t so it can use (<|>) to prepend it. liftA2 lets us abstract over the applicative a, you can imagine it as unwrapping two arguments, applying them to prepend and wrapping the result back up.

Monoid mempty in pattern matching

I tried to write a generalized maximum function similar to the one in Prelude. My first naiv approach looked like this:
maximum' :: (F.Foldable a, Ord b) => a b -> Maybe b
maximum' mempty = Nothing
maximum' xs = Just $ F.foldl1 max xs
However, when I test it it always returns Nothing regardless of the input:
> maximum' [1,2,3]
> Nothing
Now I wonder whether it's possible to obtain the empty value of a Monoid type instance. A test function I wrote works correctly:
getMempty :: (Monoid a) => a -> a
getMempty _ = mempty
> getMempty [1,2,3]
> []
I had already a look at these two questions but I didn't figure out how the answers solve my problem:
Write a Maximum Monoid using Maybe in Haskell
Haskell Pattern Matching on the Empty Set
How would I rewrite the maximum' function to get it to work ?
As C. A. McCann points out in his comment, you can't pattern match on values, only patterns.
The equation maximum' mempty = Nothing is actually equivalent to the equation maximum' x = Nothing. The argument gets bound to a name and Nothing is returned.
Here's a way to make your code work:
maximum' :: (F.Foldable a, Ord b, Eq (a b), Monoid (a b)) => a b -> Maybe b
maximum' xs
| xs == mempty = Nothing
| otherwise = Just $ F.foldl1 max xs
I.e. you can compare the value xs against mempty. Note that we need a Monoid constraint to be able to get at the value mempty :: a b and an Eq constraint to be able to compare as well.
An other, more elegant, solution would be to use a fold to differentiate between the empty and non-empty cases:
maximum'' :: (F.Foldable a, Ord b) => a b -> Maybe b
maximum'' xs = F.foldl max' Nothing xs
where max' Nothing x = Just x
max' (Just y) x = Just $ max x y
There are a few ways to do this (the one #opqdonut demonstrates is good). One could also make a "maximum" monoid around Maybe, and use foldMap.
newtype Maximum a = Max { unMaximum :: Maybe a }
instance (Ord a) => Monoid (Maximum a) where
mempty = Max Nothing
mappend (Max Nothing) b = b
mappend a (Max Nothing) = a
mappend (Max (Just a)) (Max (Just b)) = Max . Just $ (max a b)
maximum' = unMaximum . F.foldMap (Max . Just)
There are many ways, one is (as you mention) to create an instance of Monoid. However, we need to wrap it to Maybe to distinguish the case when we have no values. The implementation might look like this:
import Data.Monoid (Monoid, mempty, mappend)
import qualified Data.Foldable as F
-- Either we have a maximum value, or Nothing, if the
-- set of values is empty.
newtype Maximum a = Maximum { getMaximum :: Maybe a }
deriving (Eq, Ord, Read, Show)
instance Ord a => Monoid (Maximum a) where
mempty = Maximum Nothing
-- If one part is Nothing, just take the other one.
-- If both have a value, take their maximum.
(Maximum Nothing) `mappend` y = y
x `mappend` (Maximum Nothing) = x
(Maximum (Just x)) `mappend` (Maximum (Just y))
= Maximum (Just $ x `max` y)
maximum' :: (F.Foldable t, Ord a) => t a -> Maximum a
maximum' = F.foldMap (Maximum . Just)
As many have already told you, you can't pattern match on a value.
As fewer people have told you, pattern matching is arguably the Haskell equivalent of object fields in a language like Java: it's valuable for internal consumption by tightly coupled code, but probably not something you wish to expose to external client code. Basically, if you let a piece of code know your type's constructors, now you can never change these constructors without changing that other piece of code—even if your type's semantics did not really change.
The best solution here is really to just use Foldable.foldr:
maximum' :: (F.Foldable a, Ord b) => a b -> Maybe b
maximum' = F.foldr step Nothing
where step x Nothing = Just x
step x (Just y) = Just (max x y)
Note that foldr is a generalized destructor or eliminator for Foldable instances: its two arguments are "what to do with a non-empty Foldable" and "what to do with mempty. This is more abstract and reusable than pattern matching.
How about
maximum' :: (Monoid (t a), F.Foldable t, Ord a, Eq (t a)) => t a -> Maybe a
maximum' xs
| xs == mempty = Nothing
| otherwise = Just $ F.foldl1 max xs
You were missing a guard.
On the getEmpty function, you don't need it. Just use mempty, and allow its type to be inferred.

Repacking monads -- any generic way?

Given two monads, Monad m and Monad n, I would like to transform m (n a) into n (m a). But there seems to be no generic way because both (>>=) and return deals with only one monad type, and although (>>=) allows extracting content from a monad, you must pack them back to the same monad type so it can be a result value.
However, if we set m to a fixed type, the job becomes easy. Take Maybe as an example:
reorder :: (Monad n) => Maybe (n a) -> n (Maybe a)
reorder Nothing = return Nothing
reorder (Just x) = do
x' <- x
return $ Just x'
Or a list:
reorder :: (Monad n) => [n a] -> n [a]
reorder [] = return []
reorder (x:xs) = do
x' <- x
xs' <- reorder xs
return (x':xs')
Not hard to see, we've got a pattern here. To be more obvious, write it in a Applicative way, and it's no more than applying the data constructor to each element:
reorder (Just x) = Just <$> x
reorder (x:xs) = (:) <$> x <*> (reorder xs)
My question is: does a haskell typeclass already exist to describe such operations, or do I have to invent the wheel myself?
I had a brief search in the GHC documentation, and found nothing useful for this topic.
Data.Traversable provides what you are looking for:
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
GHC even provides support for automatically deriving instances:
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
import Data.Foldable
import Data.Traversable
data List a = Nil | Cons a (List a)
deriving(Functor, Foldable, Traversable)
A quick search on hoogle for (Monad m, Monad n) => m (n a) -> n (m a) showed me that there are several functions that (roughly) comply with the signature you're looking for:
Data.Traversable.sequence :: (Traversable t, Monad m) => t (m a) -> m (t a);
Data.Traversable.sequenceA :: Applicative f => t (f a) -> f (t a);
Contro.Monad.sequence :: Monad m => [m a] -> m [a] (also exported by Prelude).
Both [a] and Maybe a are instances of traversable, so your reorder functions are just applications of Data.Traversable.sequence. One could write, in example:
ghci> (Data.Traversable.sequence $ Just (return 1)) :: IO (Maybe Int)
Just 1
it :: Maybe Int
ghci> (Data.Traversable.sequence $ Just ([1])) :: [Maybe Int]
[Just 1]
it :: [Maybe Int]
ghci> (Data.Traversable.sequence $ [Just 1]) :: Maybe [Int]
Just [1]
it :: Maybe [Int]
Please note however that the specific class declaration is class (Functor t, Foldable t) => Traversable t, and if you look also at the types of the other two functions, it does not seems like what you're looking for could possibly be done in a generic way for all monads m and n without restrictions/preconditions.
It can't be done in general: a good example of a monad that can't do this is the reader (or function) monad. That would require the following function to be definable:
impossible :: (r -> IO a) -> IO (r -> a)
It's not straightforward to prove that a function cannot be implemented. But intuitively, the problem is that whatever IO has to be done in the value returned has to be done before we know what the r parameter is. So impossible readFile would have to yield a pure function FilePath -> String before it knew which files to open. Clearly, at least, impossible can't do what you'd want it to.
Not all Monads can commute in that way. Edward Kmett's distributive package provides a typeclass Distributive for type constructors that is similar to what you desire (simplified):
class Functor g => Distributive g where
distribute :: Functor f => f (g a) -> g (f a)
collect :: Functor f => (a -> g b) -> f a -> g (f b)
Default definitions are provided for distribute and collect, written in terms of each other. I found this package by searching hayoo for the desired type signature.

Resources