selective-0.4: Selective applicative functors

Copyright(c) Andrey Mokhov 2018-2019
LicenseMIT (see the file LICENSE)
Maintainerandrey.mokhov@gmail.com
Stabilityexperimental
Safe HaskellNone
LanguageHaskell2010

Control.Selective

Contents

Description

This is a library for selective applicative functors, or just selective functors for short, an abstraction between applicative functors and monads, introduced in this paper: https://www.staff.ncl.ac.uk/andrey.mokhov/selective-functors.pdf.

Synopsis

Type class

class Applicative f => Selective f where Source #

Selective applicative functors. You can think of select as a selective function application: when given a value of type Left a, you must apply the given function, but when given a Right b, you may skip the function and associated effects, and simply return the b.

Note that it is not a requirement for selective functors to skip unnecessary effects. It may be counterintuitive, but this makes them more useful. Why? Typically, when executing a selective computation, you would want to skip the effects (saving work); but on the other hand, if your goal is to statically analyse a given selective computation and extract the set of all possible effects (without actually executing them), then you do not want to skip any effects, because that defeats the purpose of static analysis.

The type signature of select is reminiscent of both <*> and >>=, and indeed a selective functor is in some sense a composition of an applicative functor and the Either monad.

Laws:

  • Identity:
x <*? pure id = either id id <$> x
  • Distributivity; note that y and z have the same type f (a -> b):
pure x <*? (y *> z) = (pure x <*? y) *> (pure x <*? z)
  • Associativity:
x <*? (y <*? z) = (f <$> x) <*? (g <$> y) <*? (h <$> z)
  where
    f x = Right <$> x
    g y = a -> bimap (,a) ($a) y
    h z = uncurry z
  • Monadic select (for selective functors that are also monads):
select = selectM

There are also a few useful theorems:

  • Apply a pure function to the result:
f <$> select x y = select (fmap f <$> x) (fmap f <$> y)
  • Apply a pure function to the Left case of the first argument:
select (first f <$> x) y = select x ((. f) <$> y)
  • Apply a pure function to the second argument:
select x (f <$> y) = select (first (flip f) <$> x) ((&) <$> y)
  • Generalised identity:
x <*? pure y = either y id <$> x
  • A selective functor is rigid if it satisfies <*> = apS. The following interchange law holds for rigid selective functors:
x *> (y <*? z) = (x *> y) <*? z

If f is also a Monad, we require that select = selectM, from which one can prove <*> = apS.

Methods

select :: f (Either a b) -> f (a -> b) -> f b Source #

Instances
Selective [] Source # 
Instance details

Defined in Control.Selective

Methods

select :: [Either a b] -> [a -> b] -> [b] Source #

Selective Maybe Source # 
Instance details

Defined in Control.Selective

Methods

select :: Maybe (Either a b) -> Maybe (a -> b) -> Maybe b Source #

Selective IO Source # 
Instance details

Defined in Control.Selective

Methods

select :: IO (Either a b) -> IO (a -> b) -> IO b Source #

Selective ZipList Source # 
Instance details

Defined in Control.Selective

Methods

select :: ZipList (Either a b) -> ZipList (a -> b) -> ZipList b Source #

Selective Identity Source # 
Instance details

Defined in Control.Selective

Methods

select :: Identity (Either a b) -> Identity (a -> b) -> Identity b Source #

Selective STM Source # 
Instance details

Defined in Control.Selective

Methods

select :: STM (Either a b) -> STM (a -> b) -> STM b Source #

Selective NonEmpty Source # 
Instance details

Defined in Control.Selective

Methods

select :: NonEmpty (Either a b) -> NonEmpty (a -> b) -> NonEmpty b Source #

Selective (Either e) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Either e (Either a b) -> Either e (a -> b) -> Either e b Source #

Monoid a => Selective ((,) a) Source # 
Instance details

Defined in Control.Selective

Methods

select :: (a, Either a0 b) -> (a, a0 -> b) -> (a, b) Source #

Selective (ST s) Source # 
Instance details

Defined in Control.Selective

Methods

select :: ST s (Either a b) -> ST s (a -> b) -> ST s b Source #

ArrowChoice a => Selective (ArrowMonad a) Source # 
Instance details

Defined in Control.Selective

Methods

select :: ArrowMonad a (Either a0 b) -> ArrowMonad a (a0 -> b) -> ArrowMonad a b Source #

Selective (Proxy :: Type -> Type) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Proxy (Either a b) -> Proxy (a -> b) -> Proxy b Source #

Selective f => Selective (Lift f) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Lift f (Either a b) -> Lift f (a -> b) -> Lift f b Source #

Monad m => Selective (MaybeT m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: MaybeT m (Either a b) -> MaybeT m (a -> b) -> MaybeT m b Source #

Semigroup e => Selective (Validation e) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Validation e (Either a b) -> Validation e (a -> b) -> Validation e b Source #

Monoid m => Selective (Under m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Under m (Either a b) -> Under m (a -> b) -> Under m b Source #

Monoid m => Selective (Over m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Over m (Either a b) -> Over m (a -> b) -> Over m b Source #

Monad f => Selective (SelectM f) Source # 
Instance details

Defined in Control.Selective

Methods

select :: SelectM f (Either a b) -> SelectM f (a -> b) -> SelectM f b Source #

Applicative f => Selective (SelectA f) Source # 
Instance details

Defined in Control.Selective

Methods

select :: SelectA f (Either a b) -> SelectA f (a -> b) -> SelectA f b Source #

Selective (Select f) Source # 
Instance details

Defined in Control.Selective.Free

Methods

select :: Select f (Either a b) -> Select f (a -> b) -> Select f b Source #

Functor f => Selective (Select f) Source # 
Instance details

Defined in Control.Selective.Rigid.Free

Methods

select :: Select f (Either a b) -> Select f (a -> b) -> Select f b Source #

Selective (Select f) Source # 
Instance details

Defined in Control.Selective.Rigid.Freer

Methods

select :: Select f (Either a b) -> Select f (a -> b) -> Select f b Source #

(Monoid w, Monad m) => Selective (WriterT w m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: WriterT w m (Either a b) -> WriterT w m (a -> b) -> WriterT w m b Source #

(Monoid w, Monad m) => Selective (WriterT w m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: WriterT w m (Either a b) -> WriterT w m (a -> b) -> WriterT w m b Source #

Monad m => Selective (StateT s m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: StateT s m (Either a b) -> StateT s m (a -> b) -> StateT s m b Source #

Monad m => Selective (StateT s m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: StateT s m (Either a b) -> StateT s m (a -> b) -> StateT s m b Source #

Monad m => Selective (IdentityT m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: IdentityT m (Either a b) -> IdentityT m (a -> b) -> IdentityT m b Source #

Monad m => Selective (ExceptT e m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: ExceptT e m (Either a b) -> ExceptT e m (a -> b) -> ExceptT e m b Source #

Selective ((->) a :: Type -> Type) Source # 
Instance details

Defined in Control.Selective

Methods

select :: (a -> Either a0 b) -> (a -> (a0 -> b)) -> a -> b Source #

(Selective f, Selective g) => Selective (Product f g) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Product f g (Either a b) -> Product f g (a -> b) -> Product f g b Source #

Monad m => Selective (ReaderT r m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: ReaderT r m (Either a b) -> ReaderT r m (a -> b) -> ReaderT r m b Source #

Selective (ContT r m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: ContT r m (Either a b) -> ContT r m (a -> b) -> ContT r m b Source #

(Applicative f, Selective g) => Selective (Compose f g) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Compose f g (Either a b) -> Compose f g (a -> b) -> Compose f g b Source #

(Monoid w, Monad m) => Selective (RWST r w s m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: RWST r w s m (Either a b) -> RWST r w s m (a -> b) -> RWST r w s m b Source #

(Monoid w, Monad m) => Selective (RWST r w s m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: RWST r w s m (Either a b) -> RWST r w s m (a -> b) -> RWST r w s m b Source #

(<*?) :: Selective f => f (Either a b) -> f (a -> b) -> f b infixl 4 Source #

An operator alias for select, which is sometimes convenient. It tries to follow the notational convention for Applicative operators. The angle bracket pointing to the left means we always use the corresponding value. The value on the right, however, may be skipped, hence the question mark.

branch :: Selective f => f (Either a b) -> f (a -> c) -> f (b -> c) -> f c Source #

The branch function is a natural generalisation of select: instead of skipping an unnecessary effect, it chooses which of the two given effectful functions to apply to a given argument; the other effect is unnecessary. It is possible to implement branch in terms of select, which is a good puzzle (give it a try!).

We can also implement select via branch:

selectB :: Selective f => f (Either a b) -> f (a -> b) -> f b
selectB x y = branch x y (pure id)

selectA :: Applicative f => f (Either a b) -> f (a -> b) -> f b Source #

We can write a function with the type signature of select using the Applicative type class, but it will always execute the effects associated with the second argument, hence being potentially less efficient.

apS :: Selective f => f (a -> b) -> f a -> f b Source #

Recover the application operator <*> from select. Rigid selective functors satisfy the law <*> = apS and furthermore, the resulting applicative functor satisfies all laws of Applicative:

  • Identity:

    pure id <*> v = v
  • Homomorphism:

    pure f <*> pure x = pure (f x)
  • Interchange:

    u <*> pure y = pure ($y) <*> u
  • Composition:

    (.) <$> u <*> v <*> w = u <*> (v <*> w)

selectM :: Monad f => f (Either a b) -> f (a -> b) -> f b Source #

One can easily implement a monadic selectM that satisfies the laws, hence any Monad is Selective.

Conditional combinators

ifS :: Selective f => f Bool -> f a -> f a -> f a Source #

Branch on a Boolean value, skipping unnecessary effects.

whenS :: Selective f => f Bool -> f () -> f () Source #

Conditionally perform an effect.

fromMaybeS :: Selective f => f a -> f (Maybe a) -> f a Source #

A lifted version of fromMaybe.

orElse :: (Selective f, Semigroup e) => f (Either e a) -> f (Either e a) -> f (Either e a) Source #

Return the first Right value. If both are Left's, accumulate errors.

andAlso :: (Selective f, Semigroup a) => f (Either e a) -> f (Either e a) -> f (Either e a) Source #

Accumulate the Right values, or return the first Left.

untilRight :: (Monoid a, Selective f) => f (Either a b) -> f (a, b) Source #

Keep running an effectful computation until it returns a Right value, collecting the Left's using a supplied Monoid instance.

whileS :: Selective f => f Bool -> f () Source #

Keep checking an effectful condition while it holds.

(<||>) :: Selective f => f Bool -> f Bool -> f Bool Source #

A lifted version of lazy Boolean OR.

(<&&>) :: Selective f => f Bool -> f Bool -> f Bool Source #

A lifted version of lazy Boolean AND.

foldS :: (Selective f, Foldable t, Monoid a) => t (f (Either e a)) -> f (Either e a) Source #

Generalised folding with the short-circuiting behaviour.

anyS :: Selective f => (a -> f Bool) -> [a] -> f Bool Source #

A lifted version of any. Retains the short-circuiting behaviour.

allS :: Selective f => (a -> f Bool) -> [a] -> f Bool Source #

A lifted version of all. Retains the short-circuiting behaviour.

bindS :: (Bounded a, Enum a, Eq a, Selective f) => f a -> (a -> f b) -> f b Source #

A restricted version of monadic bind. Fails with an error if the Bounded and Enum instances for a do not cover all values of a.

data Cases a Source #

A list of values, equipped with a fast membership test.

casesEnum :: (Bounded a, Enum a) => Cases a Source #

The list of all possible values of an enumerable data type.

cases :: Eq a => [a] -> Cases a Source #

Embed a list of values into Cases using the trivial but slow membership test based on elem.

matchS :: (Eq a, Selective f) => Cases a -> f a -> (a -> f b) -> f (Either a b) Source #

Eliminate all specified values a from f (Either a b) by replacing each of them with a given f a.

matchM :: Monad m => Cases a -> m a -> (a -> m b) -> m (Either a b) Source #

Eliminate all specified values a from f (Either a b) by replacing each of them with a given f a.

Selective functors

newtype SelectA f a Source #

Any applicative functor can be given a Selective instance by defining select = selectA. This data type captures this pattern, so you can use it in combination with the DerivingVia extension as follows:

newtype Over m a = Over m
    deriving (Functor, Applicative, Selective) via SelectA (Const m)

Constructors

SelectA 

Fields

Instances
Functor f => Functor (SelectA f) Source # 
Instance details

Defined in Control.Selective

Methods

fmap :: (a -> b) -> SelectA f a -> SelectA f b #

(<$) :: a -> SelectA f b -> SelectA f a #

Applicative f => Applicative (SelectA f) Source # 
Instance details

Defined in Control.Selective

Methods

pure :: a -> SelectA f a #

(<*>) :: SelectA f (a -> b) -> SelectA f a -> SelectA f b #

liftA2 :: (a -> b -> c) -> SelectA f a -> SelectA f b -> SelectA f c #

(*>) :: SelectA f a -> SelectA f b -> SelectA f b #

(<*) :: SelectA f a -> SelectA f b -> SelectA f a #

Applicative f => Selective (SelectA f) Source # 
Instance details

Defined in Control.Selective

Methods

select :: SelectA f (Either a b) -> SelectA f (a -> b) -> SelectA f b Source #

newtype SelectM f a Source #

Any monad can be given a Selective instance by defining select = selectM. This data type captures this pattern, so you can use it in combination with the DerivingVia extension as follows:

newtype V1 a = V1 a
    deriving (Functor, Applicative, Selective, Monad) via SelectM Identity

Constructors

SelectM 

Fields

Instances
Monad f => Monad (SelectM f) Source # 
Instance details

Defined in Control.Selective

Methods

(>>=) :: SelectM f a -> (a -> SelectM f b) -> SelectM f b #

(>>) :: SelectM f a -> SelectM f b -> SelectM f b #

return :: a -> SelectM f a #

fail :: String -> SelectM f a #

Functor f => Functor (SelectM f) Source # 
Instance details

Defined in Control.Selective

Methods

fmap :: (a -> b) -> SelectM f a -> SelectM f b #

(<$) :: a -> SelectM f b -> SelectM f a #

Applicative f => Applicative (SelectM f) Source # 
Instance details

Defined in Control.Selective

Methods

pure :: a -> SelectM f a #

(<*>) :: SelectM f (a -> b) -> SelectM f a -> SelectM f b #

liftA2 :: (a -> b -> c) -> SelectM f a -> SelectM f b -> SelectM f c #

(*>) :: SelectM f a -> SelectM f b -> SelectM f b #

(<*) :: SelectM f a -> SelectM f b -> SelectM f a #

Monad f => Selective (SelectM f) Source # 
Instance details

Defined in Control.Selective

Methods

select :: SelectM f (Either a b) -> SelectM f (a -> b) -> SelectM f b Source #

newtype Over m a Source #

Static analysis of selective functors with over-approximation.

Constructors

Over 

Fields

Instances
Functor (Over m) Source # 
Instance details

Defined in Control.Selective

Methods

fmap :: (a -> b) -> Over m a -> Over m b #

(<$) :: a -> Over m b -> Over m a #

Monoid m => Applicative (Over m) Source # 
Instance details

Defined in Control.Selective

Methods

pure :: a -> Over m a #

(<*>) :: Over m (a -> b) -> Over m a -> Over m b #

liftA2 :: (a -> b -> c) -> Over m a -> Over m b -> Over m c #

(*>) :: Over m a -> Over m b -> Over m b #

(<*) :: Over m a -> Over m b -> Over m a #

Monoid m => Selective (Over m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Over m (Either a b) -> Over m (a -> b) -> Over m b Source #

Eq m => Eq (Over m a) Source # 
Instance details

Defined in Control.Selective

Methods

(==) :: Over m a -> Over m a -> Bool #

(/=) :: Over m a -> Over m a -> Bool #

Ord m => Ord (Over m a) Source # 
Instance details

Defined in Control.Selective

Methods

compare :: Over m a -> Over m a -> Ordering #

(<) :: Over m a -> Over m a -> Bool #

(<=) :: Over m a -> Over m a -> Bool #

(>) :: Over m a -> Over m a -> Bool #

(>=) :: Over m a -> Over m a -> Bool #

max :: Over m a -> Over m a -> Over m a #

min :: Over m a -> Over m a -> Over m a #

Show m => Show (Over m a) Source # 
Instance details

Defined in Control.Selective

Methods

showsPrec :: Int -> Over m a -> ShowS #

show :: Over m a -> String #

showList :: [Over m a] -> ShowS #

newtype Under m a Source #

Static analysis of selective functors with under-approximation.

Constructors

Under 

Fields

Instances
Functor (Under m) Source # 
Instance details

Defined in Control.Selective

Methods

fmap :: (a -> b) -> Under m a -> Under m b #

(<$) :: a -> Under m b -> Under m a #

Monoid m => Applicative (Under m) Source # 
Instance details

Defined in Control.Selective

Methods

pure :: a -> Under m a #

(<*>) :: Under m (a -> b) -> Under m a -> Under m b #

liftA2 :: (a -> b -> c) -> Under m a -> Under m b -> Under m c #

(*>) :: Under m a -> Under m b -> Under m b #

(<*) :: Under m a -> Under m b -> Under m a #

Monoid m => Selective (Under m) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Under m (Either a b) -> Under m (a -> b) -> Under m b Source #

Eq m => Eq (Under m a) Source # 
Instance details

Defined in Control.Selective

Methods

(==) :: Under m a -> Under m a -> Bool #

(/=) :: Under m a -> Under m a -> Bool #

Ord m => Ord (Under m a) Source # 
Instance details

Defined in Control.Selective

Methods

compare :: Under m a -> Under m a -> Ordering #

(<) :: Under m a -> Under m a -> Bool #

(<=) :: Under m a -> Under m a -> Bool #

(>) :: Under m a -> Under m a -> Bool #

(>=) :: Under m a -> Under m a -> Bool #

max :: Under m a -> Under m a -> Under m a #

min :: Under m a -> Under m a -> Under m a #

Show m => Show (Under m a) Source # 
Instance details

Defined in Control.Selective

Methods

showsPrec :: Int -> Under m a -> ShowS #

show :: Under m a -> String #

showList :: [Under m a] -> ShowS #

data Validation e a Source #

Selective instance for the standard applicative functor Validation. This is a good example of a non-trivial selective functor which is not a monad.

Constructors

Failure e 
Success a 
Instances
Functor (Validation e) Source # 
Instance details

Defined in Control.Selective

Methods

fmap :: (a -> b) -> Validation e a -> Validation e b #

(<$) :: a -> Validation e b -> Validation e a #

Semigroup e => Applicative (Validation e) Source # 
Instance details

Defined in Control.Selective

Methods

pure :: a -> Validation e a #

(<*>) :: Validation e (a -> b) -> Validation e a -> Validation e b #

liftA2 :: (a -> b -> c) -> Validation e a -> Validation e b -> Validation e c #

(*>) :: Validation e a -> Validation e b -> Validation e b #

(<*) :: Validation e a -> Validation e b -> Validation e a #

Semigroup e => Selective (Validation e) Source # 
Instance details

Defined in Control.Selective

Methods

select :: Validation e (Either a b) -> Validation e (a -> b) -> Validation e b Source #

(Show e, Show a) => Show (Validation e a) Source # 
Instance details

Defined in Control.Selective

Methods

showsPrec :: Int -> Validation e a -> ShowS #

show :: Validation e a -> String #

showList :: [Validation e a] -> ShowS #

Miscellaneous

swapEither :: Either a b -> Either b a Source #

Swap Left and Right.

newtype ComposeEither f e a Source #

Composition of a functor f with the Either monad.

Constructors

ComposeEither (f (Either e a)) 
Instances
Functor f => Functor (ComposeEither f e) Source # 
Instance details

Defined in Control.Selective

Methods

fmap :: (a -> b) -> ComposeEither f e a -> ComposeEither f e b #

(<$) :: a -> ComposeEither f e b -> ComposeEither f e a #

Applicative f => Applicative (ComposeEither f e) Source # 
Instance details

Defined in Control.Selective

Methods

pure :: a -> ComposeEither f e a #

(<*>) :: ComposeEither f e (a -> b) -> ComposeEither f e a -> ComposeEither f e b #

liftA2 :: (a -> b -> c) -> ComposeEither f e a -> ComposeEither f e b -> ComposeEither f e c #

(*>) :: ComposeEither f e a -> ComposeEither f e b -> ComposeEither f e b #

(<*) :: ComposeEither f e a -> ComposeEither f e b -> ComposeEither f e a #

(Selective f, Monoid e) => Alternative (ComposeEither f e) Source # 
Instance details

Defined in Control.Selective

Methods

empty :: ComposeEither f e a #

(<|>) :: ComposeEither f e a -> ComposeEither f e a -> ComposeEither f e a #

some :: ComposeEither f e a -> ComposeEither f e [a] #

many :: ComposeEither f e a -> ComposeEither f e [a] #