3

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?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
TippFehler
  • 341
  • 1
  • 4

2 Answers2

7

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:

Will Ness
  • 70,110
  • 9
  • 98
  • 181
3

Functor and Applicative are both too weak: Monad contains the function you seek.

applyToRight = flip (>>=)
amalloy
  • 89,153
  • 8
  • 140
  • 205