Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 452
Adam Avatar asked Sep 15 '25 05:09

Adam


2 Answers

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)
like image 105
Louis Wasserman Avatar answered Sep 17 '25 03:09

Louis Wasserman


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+)
like image 29
Willem Van Onsem Avatar answered Sep 17 '25 01:09

Willem Van Onsem