[Haskell-cafe] Applicative functors with branch/choice ?

Twan van Laarhoven twanvl at gmail.com
Thu Jul 26 00:34:21 CEST 2012

On 2012-07-25 22:22, Евгений Пермяков wrote:
> Let assume, that some computation takes argument and produces value Either a b.
> This computation may be represented in for different forms
> ====
> computePure :: a -> Either b c
> computeMonad :: a -> m (Either b c)
> computeApplicative :: app a -> app (Either b c)
> computeArrow :: arr a (Either b c)
> =====
> And now, having result, we need to execute several actions, making a choice,
> what actions to perform for Left and Right tags of Either. Pure function and
> monads are easy, as there is way to pattern-match on value and take actions
> depending on result. There is an extension to Arrow class that do the job --
> ArrowChoice. However, I cannot find any way to make choice for Applicative. It
> seems that both Applicative and Alternative are not suited for it.
> So, it seems for me, that Applicative API should be extended with typeclass for
> making choice what actions to execute depending on result of some test (pattern
> matching). Is there any reasonable definition of such typeclass or clear
> explanation, why such typeclass is unneeded?
> The possible extension may look somehow like this:
> class Applicative a => Branching a where
>   branch :: a (Either b c) -> (a b -> a d) -> (a c -> a d) -> a d

A nicer typeclass is perhaps the dual to applicative. Given a functor, (<*>) is 
equivalent to the function pair:

     class Functor f => Pairing f where
         pair :: (f a, f b) -> f (a,b)
         -- pair (x,y) = (,) <$> x <*> y
         -- (<*>) x y = ($) <$> pair (x,y)

You can form the dual of pair by flipping the arrows and replacing products by 
sums, which gives:

     class Functor f => Branching f where
         liftEither :: f (Either a b) -> Either (f a, f b)

Which looks almost equivalent to your Branching class. But I can't think of any 
non-trivial functors that are an instance of this class. Perhaps a better 
typeclass is the one where you keep the product on the result side:

     class Functor => Partitionable f where
         partitionEithers :: f (Either a b) -> (f a, f b)

You can build some useful functions on top of partionEithers, such as 
`partition` and `filter`.

     filter = fst . partition
     partition pred = partitionEithers . fmap side
         where side x = if pred x then Left x else Right x

I don't know if it is enough for your ArrowChoice instance.


More information about the Haskell-Cafe mailing list