[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