Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-input monadic functions with currying in Haskell

I have a function like so

foo :: X -> Y -> Z

and I have two separate calculations that are done to get my variables of type X and Y, but they can fail, so I use a Maybe

calc1 :: A -> Maybe X
calc2 :: B -> Maybe Y

now I am not sure how to use the monad operations to get this desired behaviour

safe_foo :: Maybe X -> Maybe Y -> Maybe Z
safe_foo Nothing _ = Nothing
safe_foo _ Nothing = Nothing
safe_foo (Just x) (Just y) = Just (foo x y)

what is the best way to do this?

like image 308
Abe Avatar asked Sep 01 '20 15:09

Abe


2 Answers

You just need liftA2, which is defined as part of the Applicative type class.

safe_foo = liftA2 foo

Or alternatively, in the "applicative style":

safe_foo mx my = foo <$> mx <*> my
like image 128
Robin Zigmond Avatar answered Oct 17 '22 16:10

Robin Zigmond


You could use the monad with a do block

safe_foo mx my = do    -- BTW, we underscore_case is unconventional in Haskell,
   x <- mx             -- preferrably use camelCase instead
   y <- my
   return $ foo x y

...or, desugared&simplified,

safe_foo mx my = mx >>= (<$>my) . foo

but really you don't need Monad here, Applicative is enough.

safe_foo = liftA2 foo

or directly using the calc-functions,

   foo <$> calc1 a <*> calc2 b
like image 5
leftaroundabout Avatar answered Oct 17 '22 17:10

leftaroundabout