Adam
Adam

Reputation: 3003

How do you idiomatically add 1 to two Maybe Int and then multiply them together in haskell

Yesterday I read up some on the whole monad thing. I by no means grasp it, but it will not stop me from trying to use it. Some of the answers in this question really do push that monads is there to make things nicer, and more readable. 'Haskell has nice support for monads', does that mean that I can write nice code with for example maybe out of the box?

Or does it mean that I can write code for the maybe type which makes it easy to use.

I encountered the following problem when doing advent of code:

Add 1 to the values in two Maybes and then multiply them together.

After reading question on multiplying two maybes and also checking out typeclassopedia I arrived at (after some serious head scratching):

let test = Just (*) <*> ((+1) <$> marker1Pos) <*> ((+1) <$> marker2Pos)

It works, but to me that looks less than ideal.

Can I do it with a do-block which I read about in the first link?

Upvotes: 4

Views: 249

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476594

You can work with on :: (b -> b -> c) -> (a -> b) -> a -> a -> c here:

import Control.Applicative(liftA2)
import Data.Function(on)

f :: (Applicative f, Num a) => f a -> f a -> f a   
f = liftA2 (*) `on` fmap (1+)

Upvotes: 4

Louis Wasserman
Louis Wasserman

Reputation: 198083

Sure, you can do it with a do.

do  x <- marker1Pos
    y <- marker2Pos
    return ((x + 1) * (y + 1))

I would also tend to use liftM2 or liftA2 for the version you wrote, and I'd also tend to use fmap instead of <$> for sections. You may or may not find this more appealing, but I offer it in case you do:

liftA2 (*) (fmap (+1) marker1Pos) (fmap (+1) marker2Pos)

Upvotes: 10

Related Questions