Reputation: 351
Say I have function two functions f
and g
that both take in regular values and return an Either
value like so:
g :: a -> Either x b
f :: b -> Either x c
How do I chain the two together to get something like f . g
?
The best solution I have come up with is creating a helper function called applyToRight
that works like this
applyToRight :: (a -> Either x b) -> Either x a -> Either x b
applyToRight f x =
case x of
Left a -> Left a
Right b -> f b
So that I can then do
applyToRight f (g a)
In this case I am specifically talking about Either
, but I think this problem could be generalized to all applicative functors. What is the most elegant way to deal with this?
Upvotes: 3
Views: 174
Reputation: 71065
Not Applicative. You have rediscovered the Monadic bind:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Either x
is a Monad:
> Left "a" >>= (\x -> Right (1+x))
Left "a"
> Right 1 >>= (\x -> Right (1+x))
Right 2
Chaining two monad-creating functions like you have is done with the Kleisli composition operator, like f <=< g
, or equivalently in the other direction g >=> f
with the forward composition operator,
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
the types are easier to follow with this one:
f :: b -> Either x c
g :: a -> Either x b
-----------------------------------------
g >=> f :: a -> Either x c
In fact one way to summarize the monads is to say they are about the generalized function composition.
>=>
is defined simply as
(g >=> f) x = g x >>= f
(f <=< g) x = g x >>= f = f =<< g x
See also:
Upvotes: 7
Reputation: 91857
Functor and Applicative are both too weak: Monad contains the function you seek.
applyToRight = flip (>>=)
Upvotes: 3