I'm fairly new to Haskell and functional programming and I have recently been learning about Functors, Applicatives and Monads. While I seem to understand the basics, I have trouble figuring out the best/most idiomatic way apply function arguments when the type of some arguments changes to an Applicative. Consider the following, simple code:
myfun :: Int -> Int -> Int -> Int
myfun a b c = a + b + c -- lets pretend this does something more complicated
a = 5
b = 10
c = 20
result = myfun a b c
Using myfun to calculate the result is fairly straightforward. However, as our requirements change, our inputs a, b and c may change to be i.e. Maybe Int or [Int] rather then Int. We can still use our unmodified myfun by doing one of the following:
result = myfun <$> a <*> b <*> c -- either like this
result = liftA3 myfun a b c -- or like that
However, in practice the arguments a, b and c may not always end up to be inside the same Applicative, and thus the two methods mentioned above would not work. What is the best way to still make the myfun function work without modifying it? Consider the following scenarios for a, b and c:
- Some are
Int, some areMaybe Int(result of the application would beMaybe Int) - Some are
Maybe Int, some areEither String Int(result could beMaybe IntorEither String Int, with the semantics of short-circuiting the calculation if any argument isNothingorLeft) - Some are
[Int], some areMaybe Int(result should beMaybe [Int], with the semantics of calculating all possible combinations as if all arguments were[Int], then wrapping that inside aJust, unless on of the Maybies areNothing, in which case we short-circuit toNothing)
Any insights are very much appreciated!