HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulerebase-1.21.2Haskell2010

Rebase.Control.Selective

  • 8 types
  • 1 class
  • 24 values
  • Packagerebase-1.21.2
  • Exports33
  • LanguageHaskell2010
  • LicenceMIT
  • SourceSelective.hs
valuecases :: Eq a => [a] -> Cases a
#

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

classclass Applicative f => Selective (f :: Type -> Type) where
#

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

Instances37Selective, …
datadata Validation e a
#

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

Instances6Functor, Applicative, Selective, Eq, Ord, Show
value(<*?) :: Selective f => f (Either a b) -> f (a -> b) -> f b
#

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.

newtypenewtype Over m a
#

Static analysis of selective functors with over-approximation.

Constructors

Instances6Functor, Applicative, Selective, Eq, Ord, Show
  • Functor (Over m)Defined in selective-0.7.0.1 · Control.Selective
  • Monoid m => Applicative (Over m)Defined in selective-0.7.0.1 · Control.Selective
  • Monoid m => Selective (Over m)Defined in selective-0.7.0.1 · Control.Selective
  • Eq m => Eq (Over m a)Defined in selective-0.7.0.1 · Control.Selective
  • Ord m => Ord (Over m a)Defined in selective-0.7.0.1 · Control.Selective
  • Show m => Show (Over m a)Defined in selective-0.7.0.1 · Control.Selective
newtypenewtype Under m a
#

Static analysis of selective functors with under-approximation.

Constructors

Instances8Functor, Applicative, Foldable, Traversable, Selective, Eq, …
  • Functor (Under m)Defined in selective-0.7.0.1 · Control.Selective
  • Monoid m => Applicative (Under m)Defined in selective-0.7.0.1 · Control.Selective
  • Foldable (Under m)Defined in selective-0.7.0.1 · Control.Selective
  • Traversable (Under m)Defined in selective-0.7.0.1 · Control.Selective
  • Monoid m => Selective (Under m)Defined in selective-0.7.0.1 · Control.Selective
  • Eq m => Eq (Under m a)Defined in selective-0.7.0.1 · Control.Selective
  • Ord m => Ord (Under m a)Defined in selective-0.7.0.1 · Control.Selective
  • Show m => Show (Under m a)Defined in selective-0.7.0.1 · Control.Selective
newtypenewtype ComposeEither (f :: Type -> Type) e a
#

Composition of a selective functor f with the Either monad.

Constructors

Instances4Functor, Applicative, Alternative, Selective
newtypenewtype ComposeTraversable (f :: Type -> Type) (g :: Type -> Type) a
#

Composition of a selective functor f and an applicative traversable functor g.

Constructors

Instances3Functor, Applicative, Selective
newtypenewtype SelectA (f :: Type -> Type) a
#

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

Instances3Functor, Applicative, Selective
newtypenewtype SelectM (f :: Type -> Type) a
#

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

Instances4Monad, Functor, Applicative, Selective
valueallS :: Selective f => (a -> f Bool) -> [a] -> f Bool
#

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

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

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

valueapS :: Selective f => f (a -> b) -> f a -> f b
#

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)
valuebindS :: (Bounded a, Enum a, Eq a, Selective f) => f a -> (a -> f b) -> f b
#

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.

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

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)
valueifS :: Selective f => f Bool -> f a -> f a -> f a
#

Branch on a Boolean value, skipping unnecessary effects.

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

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

valuematchS
  1. :: (Eq a, Selective f)
  2. => Cases a
  3. -> f a
  4. -> a -> f b
  5. -> f (Either a b)
#

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

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

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.

valueselectT :: Traversable f => f (Either a b) -> f (a -> b) -> f b
#

For traversable functors, we can implement select in another interesting way: the effects associated with the second argument can be skipped as long as the first argument contains only Right values.

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

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

valuewhileS :: Selective f => f Bool -> f ()
#

Keep checking an effectful condition while it holds.

datadata Cases a
#

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