Работать со списком значений 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 из возможных.

Другие вопросы по тегам