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.
Related
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
Suppose that I am writing tests for Data.Set. I would like to check that deleting elements from the set works, and so I might write something like this:
prop_deleteA it x = member x it ==> not (member x (delete x it))
assuming that it has a suitable Arbitrary instance. However, this relies on quickcheck generating values of x that happen to exist within the set, which is not in general guaranteed. It would be much better if x could be made to depend on it so as to guarantee that x is already a member of it. How might I do this?
I had the thought that I could write
prop_deleteB it f = let x = f it
in not (member x (delete x it))
where f :: Set a -> a is suitably defined by means of coarbitrary. However, coarbitrary would only allow us to define f :: Set a -> b, which unfortunately isn't what we want. My best thought so far has been to define a new type
data SetAndElement a = SetAndElement (Set a) a
which allows us to write a suitable Arbitrary instance
instance (Ord a, Arbitrary a) => Arbitrary (SetAndElement a) where
arbitrary = do it <- suchThat arbitrary (not . Set.null)
x <- elements (elems it)
return (SetAndElement it x)
allowing prop_delete to be written as
prop_deleteC (SetAndElement it x) = not (member x (delete x it))
This works, but seems a little involved; are there any better options? (If not, I'll modify the question and put this as an answer.) The actual Data.Set implementation (containers package) tests deletion by checking that (delete x) . (insert x) == id if x was not already a member of the given set.
It depends on what generators you have available. For example, if you already have setOf1 (generates a Set with at least one element) and setElements (takes elements from a Set), it can be written with forAll:
-- example implementations of both combinators
setOf1 :: (Arbitrary a, Ord a) => Gen a -> Gen (Set a)
setOf1 = fmap fromList . listOf1
setElements :: Set a -> Gen a
setElements = elements . toList
prop_delete =
forAll (setOf1 arbitrary) $ \theSet ->
forAll (setElements theSet) $ \x ->
not (member (x :: Int) (delete x theSet))
This is mostly the same as SetAndElement, but instead of a fixed data type, we're using re-usable functions that can be used for further tests:
prop_null = forAll (setOf1 (arbitrary :: Gen Integer)) $ not . null
However, even if you don't write setOf1 or setElements, forAll can be rather succinct for simple tests:
prop_delete :: (Arbitrary a, Ord a) => (NonEmptyList a) -> Property
prop_delete (NonEmpty xs) =
let theSet = fromList xs
in forAll (elements xs) $ \x ->
not (member x (delete x theSet))
If you provide setElements and NonEmptySet, this can be written as
newtype NonEmptySet x = NonEmptySet {getNonEmptySet :: Set a}
instance (Ord a, Arbitray a) => Arbitrary (NonEmptySet a) where
arbitrary = fmap NonEmptySet . setOf1 $ arbitrary
prop_delete :: (Arbitrary a, Ord a) => (NonEmptySet a) -> Property
prop_delete (NonEmptySet theSet) =
forAll (setElements theSet) $ \x ->
not (member x (delete x theSet))
That way you can use NonEmptySet for tests that require a non-empty set, and setElements only for those where you actually need to choose an element at random.
Let's say I have a function that takes some predicate f and applies it to the whole domain:
someFilter :: (Enum a, Bounded a) => (a -> Bool) -> [a]
someFilter f = filter f [minBound ..]
I also know that this predicate f returns True only for a relatively small number of arguments, e.g.
isA c = (c == 'A')
Is it possible to somehow make someFilter fast, i.e. not dependent on the number of possible values of type a, without changing its signature?
You can't really do this in general, since all you've given the function is that a is Enum and Bounded, which means you'd never be able to tell if the predicate even used == (not that you can do this anyway). Instead, you can write a custom data type that can be inspected before performing the filter:
import Control.Applicative
infixr 2 `Or`
infixr 3 `And`
data Pred a
= LessThan a
| GreaterThan a
| EqualTo a
| Generic (a -> Bool)
| And (Pred a) (Pred a)
| Or (Pred a) (Pred a)
someFilter :: (Enum a, Bounded a, Ord a) => Pred a -> [a]
someFilter p = go p [minBound ..]
where
go :: (Enum a, Bounded a, Ord a) => Pred a -> [a] -> [a]
go (LessThan x) = takeWhile (< x)
go (GreaterThan x) = dropWhile (<= x)
go (EqualTo x) = const [x]
go (Generic f) = filter f
go (And p q) = go q . go p
go (Or p q) = (++) <$> go p <*> go q
naiveFilter :: (Enum a, Bounded a) => (a -> Bool) -> [a]
naiveFilter f = filter f [minBound ..]
This gives you most of the tools you need (not all of them, this is just a rough outline) to recreate basic boolean combinations of ordering predicates with support for generic predicates. For certain cases someFilter will perform much, much better than naiveFilter, such as for someFilter (LessThan 128) :: [Word32] versus naiveFilter (< 128) :: [Word32]. On my computer the former finishes in essentially 0s, while the latter I didn't even let run to completion. You can also run queries like someFilter (And (LessThan 128) (GreaterThan 256)) :: [Word32] that finish immediately, but would take forever with naiveFilter. I've used Word32 instead of Int here to avoid the problem of negative numbers.
If you want to combine a bunch of predicates together you can do
allPs, anyPs :: [Pred a] -> Pred a
allPs = foldr1 And
anyPs = foldr1 Or
Or you could try building a balanced tree out of it, but this will suffice for simplicity. It does let you express rather complicated queries fairly easy:
> :set +s
> someFilter $ EqualTo 1 `Or` EqualTo 100 `Or` LessThan 1000 `And` GreaterThan 975 :: [Word32]
[1,100,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999]
(0.00 secs, 0 bytes)
Be warned that order of operations matters here because of takeWhile and dropWhile, and you can also end up with duplicates (try making a greater-than-or-equals and less-than-or-equals, you'll see what I mean). These fixes will start to eat at the performance of this algorithm, but in general you should see no worse performance than naiveFilter.
Consider a being Word160 and f being (== w) . sha1 for a fixed word w :: Word160, where sha1 :: Word160 -> Word160 is some implementation of SHA-1. Then the predicate is true only for a very small number of inputs (most likely 1). If you had a fast way how to find matching values, you'd be constructing an inverse function to SHA-1, which would allow you to crack digital signatures and all sorts of similar stuff. So no, there is no efficient way how to do this, unless you restrict the predicate somehow.
I want to get the minimum of two maybe values, or if one is nothing get the non-nothing one, or return nothing if both inputs are nothing. I can write a simple function to do this, but I suspect there is a way to do this without writing a custom function. Sorry, if this is a petty question, but is there a simpler way than using this custom function?
minMaybe :: Ord a => Maybe a -> Maybe a -> Maybe a
minMaybe Nothing b = b
minMaybe a Nothing = a
minMaybe (Just a) (Just b) = Just $ min a b
It is possible to satisfy the specification using operators from Control.Applicative.
myMin :: Ord x => Maybe x -> Maybe x -> Maybe x
myMin a b = min <$> a <*> b <|> a <|> b
where the <|> for Maybe implements "preference"
Nothing <|> b = b
a <|> _ = a
The thing is
min <$> Just a <*> Just b = Just (min a b)
but
min <$> Just a <*> Nothing = Nothing
which has resulted in some incorrect answers to this question. Using <|> allows you to prefer the computed min value when it's available, but recover with either individual when only one is Just.
But you should ask if it is appropriate to use Maybe in this way. With the inglorious exception of its Monoid instance, Maybe is set up to model failure-prone computations. What you have here is the extension of an existing Ord with a "top" element.
data Topped x = Val x | Top deriving (Show, Eq, Ord)
and you'll find that min for Topped x is just what you need. It's good to think of types as not just the representation of data but the equipment of data with structure. Nothing usually represents some kind of failure, so it might be better to use a different type for your purpose.
You cannot use the Applicative, or Monad instance for this, since any Nothing in those contexts will have your total result being a Nothing. That being said, the term "simpler" is highly opinionated, and your function is fine as it is.
You can write it using the Alternative instance of Maybe:
minMaybe a b = liftA2 min a b <|> a <|> b
Alternatively, you could use maxBound as default, so it'll always choose the other:
minMaybe a b = liftA2 min (d a) (d b)
where d x = x <|> Just maxBound
But I don't recommend that.
Question is about lifting function min :: Ord a ⇒ a → a → a to work with Maybes context. It's associative so Semigroup instance does exactly what you want:
min' :: forall a. Ord a => Maybe a -> Maybe a -> Maybe a
min' = coerce ((<>) #(Maybe (Min a)))
This requires ScopedTypeVariables and TypeApplications. coerce comes from Data.Coerce. More old fashioned solution given below. But version above should be more performant: coerce doesn't exist at runtime. Although GHC may eliminate fmaps there's no guarantee:
min'' :: Ord a => Maybe a -> Maybe a -> Maybe a
min'' x y = fmap getMin (fmap Min x <> fmap Min y)
P.S. I would say that your solution is just fine.
I think radomaj had a good idea.
import Data.Ord (Down (..))
import Data.Function (on)
minMaybes mx my =
getDown <$> (max `on` fmap Down) mx my
getDown (Down x) = x
We use max to prefer Just to Nothing, and then use Down so we actually get the minimum if both are Just.
Here's another, similar approach that seems a bit cleaner. Maybe can be seen a way to tack on an extra minimal value, Nothing, to an arbitrary Ord type. We can write our own type to tack on a maximal value:
data AddMax a = TheMax | Plain a deriving Eq
instance Ord a => Ord (AddMax a) where
TheMax <= Plain _ = False
_ <= TheMax = True
Plain a <= Plain b = a <= b
maybeToAddMax :: Maybe a -> AddMax a
maybeToAddMax = maybe TheMax Plain
addMaxToMaybe :: AddMax a -> Maybe a
addMaxToMaybe TheMax = Nothing
addMaxToMaybe (Plain a) = Just a
Now you can write
minMaybes mx my = addMaxToMaybe $
(min `on` maybeToAddMax) mx my
You can also pull a little sleight-of-hand:
{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
import Data.Ord
import Data.Function
import Data.Coerce
newtype AddMax a = AddMax {unAddMax :: Down (Maybe (Down a))}
deriving (Eq, Ord)
Now
minMaybes :: forall a. Ord a => Maybe a -> Maybe a -> Maybe a
minMaybes = coerce (min #(AddMax a))
I'm currently in the process of trying to learn Haskell, and ran into an odd issue regarding the Maybe monad which I can't seem to figure out.
As an experiment, I'm currently trying to take a string, convert each letter to an arbitrary number, and multiply/combine them together. Here's what I have so far:
lookupTable :: [(Char, Int)]
lookupTable = [('A', 1), ('B', 4), ('C', -6)]
strToInts :: String -> [Maybe Int]
strToInts = map lookupChar
where
lookupChar :: Char -> Maybe Int
lookupChar c = lookup c lookupTable
-- Currently fails
test :: (Num n, Ord n) => [Maybe n] -> [Maybe n]
test seq = [ x * y | (x, y) <- zip seq $ tail seq, x < y ]
main :: IO ()
main = do
putStrLn $ show $ test $ strToInts "ABC"
When I try running this, it returns the following error:
test.hs:13:16:
Could not deduce (Num (Maybe n)) arising from a use of `*'
from the context (Num n, Ord n)
bound by the type signature for
test :: (Num n, Ord n) => [Maybe n] -> [Maybe n]
at test.hs:12:9-48
Possible fix: add an instance declaration for (Num (Maybe n))
In the expression: x * y
In the expression: [x * y | (x, y) <- zip seq $ tail seq]
In an equation for `test':
test seq = [x * y | (x, y) <- zip seq $ tail seq]
I'm not 100% sure why this error is occurring, or what it exactly means, though I suspect it might be because I'm trying to multiply two Maybe monads together -- if I change the definition of test to the following, the program compiles and runs fine:
test :: (Num n, Ord n) => [Maybe n] -> [Maybe n]
test seq = [ x | (x, y) <- zip seq $ tail seq, x < y ]
I also tried changing the type declaration to the below, but that didn't work either.
test :: (Num n, Ord n) => [Maybe n] -> [Num (Maybe n)]
I'm not really sure how to go about fixing this error. I'm fairly new to Haskell, so it might just be something really simple that I'm missing, or that I've structured everything completely wrong, but this is stumping me. What am I doing wrong?
Maybe does not have a num instance so you cannot multiply them together directly. You need to somehow apply the pure function to the values inside the context. This is exactly what applicative functors are for!
Applicative functors live in Control.Applicative:
import Control.Applicative
So you have this function and you want to apply it to 2 arguments in a context:
(*) :: Num a => a -> a -> a
You probably learned about fmap, it takes a function and applies it to a value in a context. <$> is an alias for fmap. When we fmap the pure function over the maybe value we get the following result:
(*) <$> Just 5 :: Num a => Maybe (a -> a)
So now we have maybe a function and we need to apply it to maybe a value, this is exactly what the applicative functor does. Its main operator is <*> which has the signature:
(<*>) :: f (a -> b) -> f a -> f b
When we specialize it we get the function we need:
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
We apply it and the output is the number you expect.
(*) <$> Just 5 <*> Just 5 :: Num a => Maybe a
So to make your code compile you need to change your test function to use <$> and <*>, see if you can figure out how.
Reite's answer is correct, and it's generally how I'd normally recommend handling it - however, it seems to me that you don't quite understand how to work with Maybe values; if so there is little sense looking at applicative functors right now.
The definition of Maybe is basically just
data Maybe a = Nothing | Just a
Which basically means exactly what it sounds like when you read it in plain english "A value of type Maybe a is either the value Nothing for that type, or a value of the form Just a".
Now you can use pattern matching to work with that, with the example of lists:
maybeReverse :: Maybe [a] -> Maybe [a]
maybeReverse Nothing = Nothing
maybeReverse (Just xs) = Just $ reverse xs
Which basically means "If the value is Nothing, then there's nothing to reverse, so the result is Nothing again. If the value is Just xs then we can reverse xs and wrap it with Just again to turn it into a Maybe [a] value).
Of course writing functions like this for every single function we ever want to use with a Maybe value would be tedious; So higher order functions to the rescue! The observation here is that in maybeReverse we didn't do all that much with reverse, we just applied it to the contained value and wrapped the result of that in Just.
So we can write a function called liftToMaybe that does this for us:
liftToMaybe :: (a->b) -> Maybe a -> Maybe b
liftToMaybe f Nothing = Nothing
liftToMaybe f (Just a) = Just $ f a
A further observation we can make is that because functions are values, we can also have Maybe values of functions. To do anything useful with those we could again unwrap them... or notice we're in the same situation as in the last paragraph, and immediately notice that we don't really care what function exactly is in that Maybe value and just write the abstraction directly:
maybeApply :: Maybe (a->b) -> Maybe a -> Maybe b
maybeApply Nothing _ = Nothing
maybeApply _ Nothing = Nothing
maybeApply (Just f) (Just a) = Just $ f a
Which, using our liftToMaybe function above, we can simplify a bit:
maybeApply :: Maybe (a->b) -> Maybe a -> Maybe b
maybeApply Nothing _ = Nothing
maybeApply (Just f) x = liftToMaybe f x
The <$> and <*> operators in Reite's answer are basically just infix names for liftToMaybe (which is also known as fmap) and maybeApply respectively; They have the types
(<$>) :: Functor f => (a->b) -> f a -> f b
(<*>) :: Applicative f => f (a->b) -> f a -> f b
You don't really need to know what the Functor and Applicative things are right now (although you should look into them at some point; They're basically generalizations of the above Maybe functions for other kinds of "context") - basically, just replace f with Maybe and you'll see that these are basically the same functions we've talked about earlier.
Now, I leave applying this to your original problem of multiplication to you (although the other answers kinda spoil it).
You are correct, the problem is that you are trying to multiply two Maybe values together, but (*) only works in instances of Num.
As it turn out, Maybe is an instance of the Applicative typeclass. This means that you can "lift" funcions that work with a type a to functions that work with a type Maybe a.
import Control.Applicative
Two functions provided by Applicative are:
pure :: a -> f a Puts a pure value in a "neutral context". For Maybe, this is Just.
(<*>) :: f (a -> b) -> f a -> f b Lets you apply a "function in a context" to two "values in a context".
So, suppose we have this pure computation:
(*) 2 3
Here are some analogous computations in a Maybe context:
Just (*) <*> Just 2 <*> Just 3
-- result is Just 6
pure (*) <*> pure 2 <*> pure 3
-- result is Just 6 -- equivalent to the above
pure (*) <*> pure 2 <*> Nothing
-- Nothing
Nothing <*> pure 2 <*> Just 3
-- Nothing
Nothing <*> Nothing <*> Nothing
-- Nothing
If the function or one of the argument is "missing", we return Nothing.
(<*>) is the explicit application operator when working with applicatives (instead of using a blank space, as when we work with pure values).
It's instructive to explore what (<*>) does with other instances of Applicative, like []:
ghci> [succ,pred] <*> pure 3
[4,2]
ghci> [succ,pred] <*> [3]
[4,2]
ghci> pure succ <*> [2,5]
[3,6]
ghci> [succ] <*> [2,5]
[3,6]
ghci> [(+),(*)] <*> pure 2 <*> pure 3
[5,6]
ghci> [(+),(*)] <*> [2,1] <*> pure 3
[5,4,6,3]
ghci> [(+),(*)] <*> [2,1] <*> [3,7]
[5,9,4,8,6,14,3,7]