Работать со списком значений Maybe
Я могу умножить список на 2:
(* 2) <$> [1, 2, 3]
Но я хочу умножить элементы, которые просто:
(* 2) <$> [Just 1, Nothing, Just 3]
Ошибка:
* Non type-variable argument in the constraint: Num (Maybe a) (Use FlexibleContexts to permit this) * When checking the inferred type it :: forall a. (Num (Maybe a), Num a) => [Maybe a] Prelude Data.List
Еще одна попытка:
fmap (* 2) [Just 1, Nothing, Just 3]
Ошибка:
* Non type-variable argument in the constraint: Num (Maybe a) (Use FlexibleContexts to permit this) * When checking the inferred type it :: forall a. (Num (Maybe a), Num a) => [Maybe a]
Я пробовал больше вещей: map2, fmap2, map (*2) map и т. Д.
3 ответа
Решение
Вам нужно составить карту дважды: один раз, чтобы попасть внутрь списка, второй раз, чтобы попасть внутрь. Оператор <$>
только карты один раз, и вы не можете использовать один и тот же оператор дважды, поэтому вы должны добавить вызов fmap
:
fmap (* 2) <$> [Just 1, Nothing, Just 3]
Простое решение заключается в добавлении другого fmap
пройти через Maybe
слой:
GHCi> fmap (* 2) <$> [Just 1, Nothing, Just 3]
[Just 2,Nothing,Just 6]
Альтернативно, это можно выразить, используя Compose
, что позволяет обрабатывать два слоя функторов как один:
GHCi> import Data.Functor.Compose
GHCi> (* 2) <$> Compose [Just 1, Nothing, Just 3]
Compose [Just 2,Nothing,Just 6]
GHCi> getCompose $ (* 2) <$> Compose [Just 1, Nothing, Just 3]
[Just 2,Nothing,Just 6]
Вы можете написать 2 fmap
функции:
(fmap . fmap) (*2) [Just 1, Nothing, Just 3]
Первым будет fmap из списка, вторым - fmap из возможных.