Может ли "все" применяться к списку "Может быть"?

Можно ли использовать all в списке [Maybe Int]?

Я знаю, что all (< 9) [2,4,6,8,10] возвращает False, но использует список с целыми числами.

Я пытаюсь выполнить что-то подобное, за исключением списка, который выглядит так: [Just 3, Just 6, Nothing, Nothing, Just 7]

Я хочу all (<=9) [Just 3, Just 6, Nothing, Nothing, Just 7] вернуть True

Ответы

Ответ 1

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

Это работает, потому что Nothing меньше любого Just x.

В качестве альтернативы можно использовать catMaybes :: [Maybe a] -> [a] из модуля Data.Maybe для удаления Nothing s и удалить обертки Just, превратив список в список чисел, который затем можно обрабатывать, как обычно:

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

Другая альтернатива: укажите свой собственный предикат на 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]

Еще лучше: define p с помощью maybe, поскольку предлагает Zeta.

Еще одна альтернатива, использующая понимание списка и and:

and [ x <= 9 | Just x <- [Just 3, Just 6, Nothing, Nothing, Just 7] ]

Ответ 2

Несколько более эзотерическое решение, чем chi и Zeta, будет использовать Compose, так что all видит два слоя как одну структуру, содержащую числа:

GHCi> import Data.Functor.Compose
GHCi> all (<=9) $ Compose [Just 3, Just 6, Nothing, Nothing, Just 7]
True

Ответ 3

Конечно. maybe True (< 9). maybe default func использует заданную функцию func, если у вас есть Just или default, если у вас есть Nothing:

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

Вы можете использовать это, чтобы написать свою функцию allMaybe:

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

Или мы могли бы "поднять" ваш предикат до 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)

Но это скрывает только скрытый Maybe.