John Doe
John Doe

Reputation: 493

Operate on a list of Maybe values

I can multiply a list per 2:

(* 2) <$> [1, 2, 3]

But I want multiply the elements which are Just:

(* 2) <$> [Just 1, Nothing, Just 3]

Error:

* 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 

Another try:

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

Error:

* 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]

I have tried more things: map2, fmap2, map (*2) map, etc.

Upvotes: 2

Views: 1976

Answers (3)

Sagi
Sagi

Reputation: 9294

You can compose 2 fmap functions:

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

The first will be the fmap of the list, the second is the fmap of the maybe.

Upvotes: 2

Fyodor Soikin
Fyodor Soikin

Reputation: 80915

You need to map twice: once to get inside the list, second time to get inside the maybe. The operator <$> only maps once, and you can't use the same operator twice, so you have to add a call to fmap:

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

Upvotes: 7

duplode
duplode

Reputation: 34398

A straightforward solution is adding another fmap to get through the Maybe layer:

GHCi> fmap (* 2) <$> [Just 1, Nothing, Just 3]
[Just 2,Nothing,Just 6]

Alternatively, that can be expressed using Compose, which allows handling the two functor layers as one:

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]

Upvotes: 10

Related Questions