对 Maybe 值列表进行操作

Operate on a list of Maybe values

我可以将列表乘以 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等

一个简单的解决方案是添加另一个 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]

您需要映射两次:一次进入列表,第二次进入可能。运算符 <$> 只映射一次,同一个运算符不能使用两次,所以你必须添加对 fmap:

的调用
fmap (* 2) <$> [Just 1, Nothing, Just 3]

您可以编写 2 个 fmap 函数:

(fmap . fmap) (*2) [Just 1, Nothing, Just 3]

第一个是列表的fmap,第二个是maybe的fmap。