Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can 'all' be applied to a list of Maybe?

Tags:

haskell

Is it possible to use all on a [Maybe Int] list?

I know all (< 9) [2,4,6,8,10] returns False, but that is using a list with just integers.

I am trying to accomplish something similar except with a list that looks like this:
[Just 3, Just 6, Nothing, Nothing, Just 7]

I want all (<=9) [Just 3, Just 6, Nothing, Nothing, Just 7] to return True

like image 402
0248881 Avatar asked May 12 '17 07:05

0248881


3 Answers

> all (<= Just 9) [Just 3, Just 6, Nothing, Nothing, Just 7]
True

This works because Nothing is less than any Just x.

Alternatively, one can use catMaybes :: [Maybe a] -> [a] from the Data.Maybe module to discard the Nothings, and remove the Just wrappers, turning the list into a list of numbers, which can then be handled as usual:

> all (<= 9) $ catMaybes [Just 3, Just 6, Nothing, Nothing, Just 7]
True

Another alternative: define your own predicate on Maybe Int.

let p :: Maybe Int -> Bool
    p Nothing = True
    p (Just x) = x <= 9
 in all p [Just 3, Just 6, Nothing, Nothing, Just 7]

Even better: define p using maybe, as Zeta suggests.

Yet another alternative, using a list comprehension and and:

and [ x <= 9 | Just x <- [Just 3, Just 6, Nothing, Nothing, Just 7] ]
like image 175
chi Avatar answered Nov 17 '22 02:11

chi


Sure. maybe True (< 9). maybe default func uses the given function func if you have Just, or the default if you have Nothing:

ghci> all (maybe True (< 9))  [Just 3, Just 6, Nothing, Nothing, Just 7]
True

You can use that to write your allMaybe function:

allMaybe :: (a -> Bool) -> [Maybe a] -> Bool
allMaybe p = all (maybe True p)

Or we could "lift" your predicate to Maybe:

liftP :: (a -> Bool) -> Maybe a -> Bool
liftP _ Nothing  = True
liftP p (Just x) = p x
-- or simply 
-- liftP p = maybe True p

allMaybe' p = all (liftP p)

But that only hides the underlying maybe away.

like image 13
Zeta Avatar answered Nov 17 '22 03:11

Zeta


A slightly more esoteric solution than those by chi and Zeta would be using Compose so that all sees the two layers as a single structure containing numbers:

GHCi> import Data.Functor.Compose
GHCi> all (<=9) $ Compose [Just 3, Just 6, Nothing, Nothing, Just 7]
True
like image 13
duplode Avatar answered Nov 17 '22 02:11

duplode