The branch operation can be implemented efficiently on its own, and select can be efficiently implemented in terms of it. This is similar to Applicative's (<*>)/liftA2 for which a more efficient implementation may exist with one compared to the other. I propose doing something similar with Selective such that:
class Applicative f => Selective f where
{-# MINIMAL (select | branch) #-}
select :: f (Either a b) -> f (a -> b) -> f b
select x y = branch x y (pure id)
branch :: f (Either a b) -> f (a -> c) -> f (b -> c) -> f c
branch x l r = select (select (fmap (fmap Left) x) (fmap (fmap Right) l)) r
At the very least, adding branch to the class would enable a more efficient definition to be given, even if the MINIMAL is not used.
This is done for Applicative with (*>), (<*); Alternative with many and some; Monad with (>>).
The
branchoperation can be implemented efficiently on its own, andselectcan be efficiently implemented in terms of it. This is similar toApplicative's(<*>)/liftA2for which a more efficient implementation may exist with one compared to the other. I propose doing something similar withSelectivesuch that:At the very least, adding
branchto the class would enable a more efficient definition to be given, even if theMINIMALis not used.This is done for
Applicativewith(*>),(<*);Alternativewithmanyandsome;Monadwith(>>).