HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

  • Packagestreaming-0.2.4.0
  • Exports63
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceInternal.hs

An iterable streaming monad transformer

1 declaration

The Stream data type can be used to represent any effectful succession of steps arising in some monad. The form of the steps is specified by the first ("functor") parameter in Stream f m r. The monad of the underlying effects is expressed by the second parameter.

This module exports combinators that pertain to that general case. Some of these are quite abstract and pervade any use of the library, e.g.

  maps    :: (forall x . f x -> g x)     -> Stream f m r -> Stream g m r
  mapped  :: (forall x . f x -> m (g x)) -> Stream f m r -> Stream g m r
  hoist   :: (forall x . m x -> n x)     -> Stream f m r -> Stream f n r -- from the MFunctor instance
  concats :: Stream (Stream f m) m r     -> Stream f m r

(assuming here and thoughout that m or n satisfies a Monad constraint, and f or g a Functor constraint.)

Others are surprisingly determinate in content:

  chunksOf     :: Int -> Stream f m r -> Stream (Stream f m) m r
  splitsAt     :: Int -> Stream f m r -> Stream f m (Stream f m r)
  zipsWith     :: (forall x y. f x -> g y -> h (x, y))
               -> Stream f m r -> Stream g m r -> Stream h m r
  zipsWith'    :: (forall x y p. (x -> y -> p) -> f x -> g y -> h p)
               -> Stream f m r -> Stream g m r -> Stream h m r
  intercalates :: Stream f m () -> Stream (Stream f m) m r -> Stream f m r
  unzips       :: Stream (Compose f g) m r ->  Stream f (Stream g m) r
  separate     :: Stream (Sum f g) m r -> Stream f (Stream g m) r  -- cp. partitionEithers
  unseparate   :: Stream f (Stream g) m r -> Stream (Sum f g) m r
  groups       :: Stream (Sum f g) m r -> Stream (Sum (Stream f m) (Stream g m)) m r

One way to see that any streaming library needs some such general type is that it is required to represent the segmentation of a stream, and to express the equivalents of Prelude/Data.List combinators that involve 'lists of lists' and the like. See for example this post on the correct expression of a streaming 'lines' function.

The module Streaming.Prelude exports combinators relating to

Stream (Of a) m r

where Of a r = !a :> r is a left-strict pair.

This expresses the concept of a Producer or Source or Generator and easily inter-operates with types with such names in e.g. conduit, iostreams and pipes.

datadata Stream (f :: Type -> Type) (m :: Type -> Type) r
#
Instances21MFunctor, MonadError, MonadReader, MonadState, MonadTrans, MMonad, …

Constructing a Stream on a given functor

11 declarations
valueyields :: (Monad m, Functor f) => f r -> Stream f m r
#

yields is like lift for items in the streamed functor. It makes a singleton or one-layer succession.

lift :: (Monad m, Functor f)    => m r -> Stream f m r
yields ::  (Monad m, Functor f) => f r -> Stream f m r

Viewed in another light, it is like a functor-general version of yield:

S.yield a = yields (a :> ())
valuewrap :: (Monad m, Functor f) => f (Stream f m r) -> Stream f m r
#

Wrap a new layer of a stream. So, e.g.

S.cons :: Monad m => a -> Stream (Of a) m r -> Stream (Of a) m r
S.cons a str = wrap (a :> str)

and, recursively:

S.each :: (Monad m, Foldable t) => t a -> Stream (Of a) m ()
S.each = foldr (\a b -> wrap (a :> b)) (return ())

The two operations

wrap :: (Monad m, Functor f )   => f (Stream f m r) -> Stream f m r
effect :: (Monad m, Functor f ) => m (Stream f m r) -> Stream f m r

are fundamental. We can define the parallel operations yields and lift in terms of them

yields :: (Monad m, Functor f )  => f r -> Stream f m r
yields = wrap . fmap return
lift ::  (Monad m, Functor f )   => m r -> Stream f m r
lift = effect . fmap return
valuereplicates :: (Monad m, Functor f) => Int -> f () -> Stream f m ()
#

Repeat a functorial layer, command or instruction a fixed number of times.

replicates n = takes n . repeats
valuerepeats :: (Monad m, Functor f) => f () -> Stream f m r
#

Repeat a functorial layer (a "command" or "instruction") forever.

valuerepeatsM :: (Monad m, Functor f) => m (f ()) -> Stream f m r
#

Repeat an effect containing a functorial layer, command or instruction forever.

valueunfold
  1. :: (Monad m, Functor f)
  2. => s -> m (Either r (f s))
  3. -> s
  4. -> Stream f m r
#

Build a Stream by unfolding steps starting from a seed. See also the specialized unfoldr in the prelude.

unfold inspect = id -- modulo the quotient we work with
unfold Pipes.next :: Monad m => Producer a m r -> Stream ((,) a) m r
unfold (curry (:>) . Pipes.next) :: Monad m => Producer a m r -> Stream (Of a) m r
valuenever :: (Monad m, Applicative f) => Stream f m r
#

never interleaves the pure applicative action with the return of the monad forever. It is the empty of the Alternative instance, thus

never <|> a = a
a <|> never = a

and so on. If w is a monoid then never :: Stream (Of w) m r is the infinite sequence of mempty, and str1 <|> str2 appends the elements monoidally until one of streams ends. Thus we have, e.g.

Example1 expression
S.stdoutLn $ S.take 2 $ S.stdinLn <|> S.repeat " " <|> S.stdinLn  <|> S.repeat " " <|> S.stdinLn1<Enter>2<Enter>3<Enter>1 2 34<Enter>5<Enter>6<Enter>4 5 6

This is equivalent to

Example1 expression
S.stdoutLn $ S.take 2 $ foldr (<|>) never [S.stdinLn, S.repeat " ", S.stdinLn, S.repeat " ", S.stdinLn ]

Where f is a monad, (<|>) sequences the conjoined streams stepwise. See the definition of paste here, where the separate steps are bytestreams corresponding to the lines of a file.

Given, say,

data Branch r = Branch r r deriving Functor  -- add obvious applicative instance

then never :: Stream Branch Identity r is the pure infinite binary tree with (inaccessible) rs in its leaves. Given two binary trees, tree1 <|> tree2 intersects them, preserving the leaves that came first, so tree1 <|> never = tree1

Stream Identity m r is an action in m that is indefinitely delayed. Such an action can be constructed with e.g. untilJust.

untilJust :: (Monad m, Applicative f) => m (Maybe r) -> Stream f m r

Given two such items, <|> instance races them. It is thus the iterative monad transformer specially defined in Control.Monad.Trans.Iter

So, for example, we might write

Example3 expressions
let justFour str = if length str == 4 then Just str else Nothinglet four = untilJust (fmap justFour getLine)run fourone<Enter>two<Enter>three<Enter>four<Enter>"four"

The Alternative instance in Control.Monad.Trans.Free is avowedly wrong, though no explanation is given for this.

valuestreamBuild
  1. :: forall b. (r -> b) -> (m b -> b) -> (f b -> b) -> b
  2. -> Stream f m r
#

Reflect a church-encoded stream; cp. GHC.Exts.build

streamFold return_ effect_ step_ (streamBuild psi) = psi return_ effect_ step_

Transforming streams

9 declarations
valuemaps
  1. :: (Monad m, Functor f)
  2. => forall x. f x -> g x
  3. -> Stream f m r
  4. -> Stream g m r
#

Map layers of one functor to another with a transformation. Compare hoist, which has a similar effect on the monadic parameter.

maps id = id
maps f . maps g = maps (f . g)
valuemapsPost
  1. :: (Monad m, Functor g)
  2. => forall x. f x -> g x
  3. -> Stream f m r
  4. -> Stream g m r
#

Map layers of one functor to another with a transformation. Compare hoist, which has a similar effect on the monadic parameter.

mapsPost id = id
mapsPost f . mapsPost g = mapsPost (f . g)
mapsPost f = maps f

mapsPost is essentially the same as maps, but it imposes a Functor constraint on its target functor rather than its source functor. It should be preferred if fmap is cheaper for the target functor than for the source functor.

valuemapsM
  1. :: (Monad m, Functor f)
  2. => forall x. f x -> m (g x)
  3. -> Stream f m r
  4. -> Stream g m r
#

Map layers of one functor to another with a transformation involving the base monad. maps is more fundamental than mapsM, which is best understood as a convenience for effecting this frequent composition:

mapsM phi = decompose . maps (Compose . phi)

The streaming prelude exports the same function under the better name mapped, which overlaps with the lens libraries.

valuemapsMPost
  1. :: (Monad m, Functor g)
  2. => forall x. f x -> m (g x)
  3. -> Stream f m r
  4. -> Stream g m r
#

Map layers of one functor to another with a transformation involving the base monad. mapsMPost is essentially the same as mapsM, but it imposes a Functor constraint on its target functor rather than its source functor. It should be preferred if fmap is cheaper for the target functor than for the source functor.

mapsPost is more fundamental than mapsMPost, which is best understood as a convenience for effecting this frequent composition:

mapsMPost phi = decompose . mapsPost (Compose . phi)

The streaming prelude exports the same function under the better name mappedPost, which overlaps with the lens libraries.

valuemapped
  1. :: (Monad m, Functor f)
  2. => forall x. f x -> m (g x)
  3. -> Stream f m r
  4. -> Stream g m r
#

Map layers of one functor to another with a transformation involving the base monad.

This function is completely functor-general. It is often useful with the more concrete type

mapped :: (forall x. Stream (Of a) IO x -> IO (Of b x)) -> Stream (Stream (Of a) IO) IO r -> Stream (Of b) IO r

to process groups which have been demarcated in an effectful, IO-based stream by grouping functions like group, split or breaks. Summary functions like fold, foldM, mconcat or toList are often used to define the transformation argument. For example:

Example1 expression
S.toList_ $ S.mapped S.toList $ S.split 'c' (S.each "abcde")["ab","de"]

Streaming.Prelude.maps and mapped obey these rules:

maps id              = id
mapped return        = id
maps f . maps g      = maps (f . g)
mapped f . mapped g  = mapped (f <=< g)
maps f . mapped g    = mapped (fmap f . g)
mapped f . maps g    = mapped (f <=< fmap g)

Streaming.Prelude.maps is more fundamental than mapped, which is best understood as a convenience for effecting this frequent composition:

mapped phi = decompose . maps (Compose . phi)
valuemappedPost
  1. :: (Monad m, Functor g)
  2. => forall x. f x -> m (g x)
  3. -> Stream f m r
  4. -> Stream g m r
#

A version of mapped that imposes a Functor constraint on the target functor rather than the source functor. This version should be preferred if fmap on the target functor is cheaper.

valuehoistUnexposed
  1. :: (Monad m, Functor f)
  2. => forall a. m a -> n a
  3. -> Stream f m r
  4. -> Stream f n r
#

A less-efficient version of hoist that works properly even when its argument is not a monad morphism.

hoistUnexposed = hoist . unexposed

Inspecting a stream

1 declaration
valueinspect :: Monad m => Stream f m r -> m (Either r (f (Stream f m r)))
#

Inspect the first stage of a freely layered sequence. Compare Pipes.next and the replica Streaming.Prelude.next. This is the uncons for the general unfold.

unfold inspect = id
Streaming.Prelude.unfoldr StreamingPrelude.next = id

Splitting and joining Streams

6 declarations
valuesplitsAt
  1. :: (Monad m, Functor f)
  2. => Int
  3. -> Stream f m r
  4. -> Stream f m (Stream f m r)
#

Split a succession of layers after some number, returning a streaming or effectful pair.

Example2 expressions
rest <- S.print $ S.splitAt 1 $ each [1..3]1S.print rest23
splitAt 0 = return
splitAt n >=> splitAt m = splitAt (m+n)

Thus, e.g.

Example2 expressions
rest <- S.print $ splitsAt 2 >=> splitsAt 2 $ each [1..5]1234S.print rest5
valuechunksOf
  1. :: (Monad m, Functor f)
  2. => Int
  3. -> Stream f m r
  4. -> Stream (Stream f m) m r
#

Break a stream into substreams each with n functorial layers.

Example1 expression
S.print $ mapped S.sum $ chunksOf 2 $ each [1,1,1,1,1]221
valueintercalates
  1. :: (Monad m, Monad (t m), MonadTrans t)
  2. => t m x
  3. -> Stream (t m) m r
  4. -> t m r
#

Interpolate a layer at each segment. This specializes to e.g.

intercalates :: (Monad m, Functor f) => Stream f m () -> Stream (Stream f m) m r -> Stream f m r

Zipping, unzipping, separating and unseparating streams

10 declarations
valueinterleaves
  1. :: (Monad m, Applicative h)
  2. => Stream h m r
  3. -> Stream h m r
  4. -> Stream h m r
#

Interleave functor layers, with the effects of the first preceding the effects of the second. When the first stream runs out, any remaining effects in the second are ignored.

interleaves = zipsWith (liftA2 (,))
Example2 expressions
let paste = \a b -> interleaves (Q.lines a) (maps (Q.cons' '\t') (Q.lines b))Q.stdout $ Q.unlines $ paste "hello\nworld\n" "goodbye\nworld\n"hello	goodbyeworld	world
valueseparate
  1. :: (Monad m, Functor f, Functor g)
  2. => Stream (Sum f g) m r
  3. -> Stream f (Stream g m) r
#

Given a stream on a sum of functors, make it a stream on the left functor, with the streaming on the other functor as the governing monad. This is useful for acting on one or the other functor with a fold, leaving the other material for another treatment. It generalizes partitionEithers, but actually streams properly.

Example2 expressions
let odd_even = S.maps (S.distinguish even) $ S.each [1..10::Int]:t separate odd_evenseparate odd_even  :: Monad m => Stream (Of Int) (Stream (Of Int) m) ()

Now, for example, it is convenient to fold on the left and right values separately:

Example1 expression
S.toList $ S.toList $ separate odd_even[2,4,6,8,10] :> ([1,3,5,7,9] :> ())

Or we can write them to separate files or whatever:

Example3 expressions
S.writeFile "even.txt" . S.show $ S.writeFile "odd.txt" . S.show $ S.separate odd_even:! cat even.txt246810:! cat odd.txt13579

Of course, in the special case of Stream (Of a) m r, we can achieve the above effects more simply by using copy

Example1 expression
S.toList . S.filter even $ S.toList . S.filter odd $ S.copy $ each [1..10::Int][2,4,6,8,10] :> ([1,3,5,7,9] :> ())

But separate and unseparate are functor-general.

valuedecompose
  1. :: (Monad m, Functor f)
  2. => Stream (Compose m f) m r
  3. -> Stream f m r
#

Rearrange a succession of layers of the form Compose m (f x).

we could as well define decompose by mapsM:

decompose = mapped getCompose

but mapped is best understood as:

mapped phi = decompose . maps (Compose . phi)

since maps and hoist are the really fundamental operations that preserve the shape of the stream:

maps  :: (Monad m, Functor f) => (forall x. f x -> g x) -> Stream f m r -> Stream g m r
hoist :: (Monad m, Functor f) => (forall a. m a -> n a) -> Stream f m r -> Stream f n r
valueexpand
  1. :: (Monad m, Functor f)
  2. => forall a b. (g a -> b) -> f a -> h b
  3. -> Stream f m r
  4. -> Stream g (Stream h m) r
#

If Of had a Comonad instance, then we'd have

copy = expand extend

See expandPost for a version that requires a Functor g instance instead.

valueexpandPost
  1. :: (Monad m, Functor g)
  2. => forall a b. (g a -> b) -> f a -> h b
  3. -> Stream f m r
  4. -> Stream g (Stream h m) r
#

If Of had a Comonad instance, then we'd have

copy = expandPost extend

See expand for a version that requires a Functor f instance instead.

Eliminating a Stream

6 declarations
valuemapsM_
  1. :: (Functor f, Monad m)
  2. => forall x. f x -> m x
  3. -> Stream f m r
  4. -> m r
#

Map each layer to an effect, and run them all.

valuerun :: Monad m => Stream m m r -> m r
#

Run the effects in a stream that merely layers effects.

valuestreamFold
  1. :: (Functor f, Monad m)
  2. => r -> b
  3. -> m b -> b
  4. -> f b -> b
  5. -> Stream f m r
  6. -> b
#

streamFold reorders the arguments of destroy to be more akin to foldr It is more convenient to query in ghci to figure out what kind of 'algebra' you need to write.

Example1 expression
:t streamFold return join(Monad m, Functor f) =>     (f (m a) -> m a) -> Stream f m a -> m a        -- iterT
Example1 expression
:t streamFold return (join . lift)(Monad m, Monad (t m), Functor f, MonadTrans t) =>     (f (t m a) -> t m a) -> Stream f m a -> t m a  -- iterTM
Example1 expression
:t streamFold return effect(Monad m, Functor f, Functor g) =>     (f (Stream g m r) -> Stream g m r) -> Stream f m r -> Stream g m r
Example1 expression
:t \f -> streamFold return effect (wrap . f)(Monad m, Functor f, Functor g) =>     (f (Stream g m a) -> g (Stream g m a))     -> Stream f m a -> Stream g m a                 -- maps
Example1 expression
:t \f -> streamFold return effect (effect . fmap wrap . f)(Monad m, Functor f, Functor g) =>     (f (Stream g m a) -> m (g (Stream g m a)))     -> Stream f m a -> Stream g m a                 -- mapped
    streamFold done eff construct
       = eff . iterT (return . construct . fmap eff) . fmap done
valueiterTM
  1. :: (Functor f, Monad m, MonadTrans t, Monad (t m))
  2. => f (t m a) -> t m a
  3. -> Stream f m a
  4. -> t m a
#

Specialized fold following the usage of Control.Monad.Trans.Free

iterTM alg = streamFold return (join . lift)
iterTM alg = iterT alg . hoist lift
valueiterT :: (Functor f, Monad m) => (f (m a) -> m a) -> Stream f m a -> m a
#

Specialized fold following the usage of Control.Monad.Trans.Free

iterT alg = streamFold return join alg
iterT alg = runIdentityT . iterTM (IdentityT . alg . fmap runIdentityT)
valuedestroy
  1. :: (Functor f, Monad m)
  2. => Stream f m r
  3. -> f b -> b
  4. -> m b -> b
  5. -> r -> b
  6. -> b
#

Map a stream to its church encoding; compare Data.List.foldr. destroyExposed may be more efficient in some cases when applicable, but it is less safe.

   destroy s construct eff done
     = eff . iterT (return . construct . fmap eff) . fmap done $ s
   

Base functor for streams of individual items

3 declarations
datadata Of a b
#

A left-strict pair; the base functor for streams of individual elements.

Constructors

  • a :> binfixr 5
Instances25Bifoldable, Bifunctor, Bitraversable, Eq2, Ord2, Show2, …
valuelazily :: Of a b -> (a, b)
#

Note that lazily, strictly, fst', and mapOf are all so-called natural transformations on the primitive Of a functor. If we write

 type f ~~> g = forall x . f x -> g x

then we can restate some types as follows:

 mapOf            :: (a -> b) -> Of a ~~> Of b   -- Bifunctor first
 lazily           ::             Of a ~~> (,) a
 Identity . fst'  ::             Of a ~~> Identity a

Manipulation of a Stream f m r by mapping often turns on recognizing natural transformations of f. Thus maps is far more general the the map of the Streaming.Prelude, which can be defined thus:

 S.map :: (a -> b) -> Stream (Of a) m r -> Stream (Of b) m r
 S.map f = maps (mapOf f)

i.e.

 S.map f = maps (\(a :> x) -> (f a :> x))

This rests on recognizing that mapOf is a natural transformation; note though that it results in such a transformation as well:

 S.map :: (a -> b) -> Stream (Of a) m ~~> Stream (Of b) m

Thus we can maps it in turn.

valuestrictly :: (a, b) -> Of a b
#

Convert a standard Haskell pair into a left-strict pair

re-exports

16 declarations
classclass MFunctor (t :: (Type -> Type) -> k -> Type) where
#

A functor in the category of monads, using hoist as the analog of fmap:

hoist (f . g) = hoist f . hoist g

hoist id = id

Methods

  • hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b

    Lift a monad morphism from m to n into a monad morphism from (t m) to (t n)

    The first argument to hoist must be a monad morphism, even though the type system does not enforce this

Instances17MFunctor, …
classclass (MFunctor t, MonadTrans t) => MMonad (t :: (Type -> Type) -> Type -> Type) where
#

A monad in the category of monads, using lift from MonadTrans as the analog of return and embed as the analog of (=<<):

embed lift = id

embed f (lift m) = f m

embed g (embed f t) = embed (\m -> embed g (f m)) t

Methods

  • embed :: Monad n => (forall a. m a -> t n a) -> t m b -> t n b

    Embed a newly created MMonad layer within an existing layer

    embed is analogous to (=<<)

Instances8MMonad, …
classclass (forall (m :: Type -> Type). Monad m => Monad (t m)) => MonadTrans (t :: (Type -> Type) -> Type -> Type) where
#

The class of monad transformers. For any monad m, the result t m should also be a monad, and lift should be a monad transformation from m to t m, i.e. it should satisfy the following laws:

Since 0.6.0.0 and for GHC 8.6 and later, the requirement that t m be a Monad is enforced by the implication constraint forall m. Monad m => Monad (t m) enabled by the QuantifiedConstraints extension.

Ambiguity error with GHC 9.0 to 9.2.2

These versions of GHC have a bug (https://gitlab.haskell.org/ghc/ghc/-/issues/20582) which causes constraints like

(MonadTrans t, forall m. Monad m => Monad (t m)) => ...

to be reported as ambiguous. For transformers 0.6 and later, this can be fixed by removing the second constraint, which is implied by the first.

Methods

  • lift :: Monad m => m a -> t m a

    Lift a computation from the argument monad to the constructed monad.

Instances17MonadTrans, …
classclass Monad m => MonadIO (m :: Type -> Type) where
#

Monads in which IO computations may be embedded. Any monad built by applying a sequence of monad transformers to the IO monad will be an instance of this class.

Instances should satisfy the following laws, which state that liftIO is a transformer of monads:

Methods

  • liftIO :: IO a -> m a

    Lift a computation from the IO monad. This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations (i.e. IO is the base monad for the stack).

    Example
    import Control.Monad.Trans.State -- from the "transformers" library
    
    printState :: Show s => StateT s IO ()
    printState = do
      state <- get
      liftIO $ print state

    Had we omitted liftIO, we would have ended up with this error:

    • Couldn't match type ‘IO’ with ‘StateT s IO’
     Expected type: StateT s IO ()
       Actual type: IO ()

    The important part here is the mismatch between StateT s IO () and IO ().

    Luckily, we know of a function that takes an IO a and returns an (m a): liftIO, enabling us to run the program and see the expected results:

    > evalStateT printState "hello"
    "hello"
    
    > evalStateT printState 3
    3
    
Instances19MonadIO, …
newtypenewtype Compose (f :: k -> Type) (g :: k1 -> k) (a :: k1)
#

Right-to-left composition of functors. The composition of applicative functors is always applicative, but the composition of monads is not always a monad.

Examples
Example1 expression
fmap (subtract 1) (Compose (Just [1, 2, 3]))Compose (Just [0,1,2])
Example1 expression
Compose (Just [1, 2, 3]) <> Compose NothingCompose (Just [1,2,3])
Example1 expression
Compose (Just [(++ "World"), (++ "Haskell")]) <*> Compose (Just ["Hello, "])Compose (Just ["Hello, World","Hello, Haskell"])

Constructors

Instances35MFunctor, Generic1, TestEquality, Functor, Applicative, Foldable, …
datadata Sum (f :: k -> Type) (g :: k -> Type) (a :: k)
#

Lifted sum of functors.

Examples
Example1 expression
fmap (+1) (InL (Just 1))  :: Sum Maybe [] IntInL (Just 2)
Example1 expression
fmap (+1) (InR [1, 2, 3]) :: Sum Maybe [] IntInR [2,3,4]

Constructors

Instances20Generic1, Functor, Foldable, Traversable, Foldable1, Eq1, …
newtypenewtype Identity a
#

Identity functor and monad. (a non-strict monad)

Examples
Example1 expression
fmap (+1) (Identity 0)Identity 1
Example1 expression
Identity [1, 2, 3] <> Identity [4, 5, 6]Identity [1,2,3,4,5,6]
>>> do
      x <- Identity 10
      y <- Identity (x + 5)
      pure (x + y)
Identity 25

Constructors

Instances42Monad, Functor, MonadFix, Applicative, Foldable, Traversable, …
classclass Applicative f => Alternative (f :: Type -> Type) where
#

A monoid on applicative functors.

If defined, some and many should be the least solutions of the equations:

Examples
Example1 expression
Nothing <|> Just 42Just 42
Example1 expression
[1, 2] <|> [3, 4][1,2,3,4]
Example1 expression
empty <|> print (2^15)32768

Methods

  • (<|>) :: f a -> f a -> f ainfixl 3

    An associative binary operation

Instances43Alternative, …
classclass (forall a. Functor (p a)) => Bifunctor (p :: Type -> Type -> Type) where
#

A bifunctor is a type constructor that takes two type arguments and is a functor in both arguments. That is, unlike with Functor, a type constructor such as Either does not need to be partially applied for a Bifunctor instance, and the methods in this class permit mapping functions over the Left value or the Right value, or both at the same time.

Formally, the class Bifunctor represents a bifunctor from Hask -> Hask.

Intuitively it is a bifunctor where both the first and second arguments are covariant.

The class definition of a Bifunctor p uses the QuantifiedConstraints language extension to quantify over the first type argument a in its context. The context requires that p a must be a Functor for all a. In other words a partially applied Bifunctor must be a Functor. This makes Functor a superclass of Bifunctor such that a function with a Bifunctor constraint may use fmap in its implementation. Functor has been a quantified superclass of Bifunctor since base-4.18.0.0.

You can define a Bifunctor by either defining bimap or by defining both first and second. The second method must agree with fmap:

second ≡ fmap

From this it follows that:

second id ≡ id

If you supply bimap, you should ensure that:

bimap id id ≡ id

If you supply first and second, ensure:

first id ≡ id
second id ≡ id

If you supply both, you should also ensure:

bimap f g ≡ first f . second g

These ensure by parametricity:

bimap  (f . g) (h . i) ≡ bimap f h . bimap g i
first  (f . g) ≡ first  f . first  g
second (f . g) ≡ second f . second g

Methods

  • bimap :: (a -> b) -> (c -> d) -> p a c -> p b d

    Map over both arguments at the same time.

    bimap f g ≡ first f . second g
    Examples
    Example1 expression
    bimap toUpper (+1) ('j', 3)('J',4)
    Example1 expression
    bimap toUpper (+1) (Left 'j')Left 'J'
    Example1 expression
    bimap toUpper (+1) (Right 3)Right 4
  • first :: (a -> b) -> p a c -> p b c

    Map covariantly over the first argument.

    first f ≡ bimap f id
    Examples
    Example1 expression
    first toUpper ('j', 3)('J',3)
    Example1 expression
    first toUpper (Left 'j')Left 'J'
  • second :: (b -> c) -> p a b -> p a c

    Map covariantly over the second argument.

    second ≡ bimap id
    Examples
    Example1 expression
    second (+1) ('j', 3)('j',4)
    Example1 expression
    second (+1) (Right 3)Right 4
Instances12Bifunctor, …
  • Bifunctor ArgDefined in base-4.20.2.0 · Data.Semigroup
  • Bifunctor EitherDefined in base-4.20.2.0 · Data.Bifunctor
  • Bifunctor Tuple2Defined in base-4.20.2.0 · Data.Bifunctor

    Class laws for tuples hold only up to laziness. Both first id and second id are lazier than id (and fmap id):

    Example3 expressions
    first id (undefined :: (Int, Word)) `seq` ()()second id (undefined :: (Int, Word)) `seq` ()()id (undefined :: (Int, Word)) `seq` ()*** Exception: Prelude.undefined
  • Bifunctor OfDefined in streaming-0.2.4.0 · Data.Functor.Of
  • Bifunctor ConstDefined in base-4.20.2.0 · Data.Bifunctor
  • Bifunctor ConstantDefined in transformers-0.6.1.1 · Data.Functor.Constant
  • Bifunctor (Tuple3 x1)Defined in base-4.20.2.0 · Data.Bifunctor
  • Bifunctor (K1 i)Defined in base-4.20.2.0 · Data.Bifunctor
  • Bifunctor (Tuple4 x1 x2)Defined in base-4.20.2.0 · Data.Bifunctor
  • Bifunctor (Tuple5 x1 x2 x3)Defined in base-4.20.2.0 · Data.Bifunctor
  • Bifunctor (Tuple6 x1 x2 x3 x4)Defined in base-4.20.2.0 · Data.Bifunctor
  • Bifunctor (Tuple7 x1 x2 x3 x4 x5)Defined in base-4.20.2.0 · Data.Bifunctor
valuejoin :: Monad m => m (m a) -> m a
#

The join function is the conventional monad join operator. It is used to remove one level of monadic structure, projecting its bound argument into the outer level.

'join bss' can be understood as the do expression

do bs <- bss
   bs
Examples
Example1 expression
join [[1, 2, 3], [4, 5, 6], [7, 8, 9]][1,2,3,4,5,6,7,8,9]
Example1 expression
join (Just (Just 3))Just 3

A common use of join is to run an IO computation returned from an GHC.Conc.STM transaction, since GHC.Conc.STM transactions can't perform IO directly. Recall that

GHC.Internal.Conc.atomically :: STM a -> IO a

is used to run GHC.Conc.STM transactions atomically. So, by specializing the types of GHC.Internal.Conc.atomically and join to

GHC.Internal.Conc.atomically :: STM (IO b) -> IO (IO b)
join       :: IO (IO b)  -> IO b

we can compose them as

join . GHC.Internal.Conc.atomically :: STM (IO b) -> IO b

to run an GHC.Conc.STM transaction and the IO action it returns.

valueliftM :: Monad m => (a1 -> r) -> m a1 -> m r
#

Promote a function to a monad. This is equivalent to fmap but specialised to Monads.

valueliftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
#

Promote a function to a monad, scanning the monadic arguments from left to right.

Examples
Example1 expression
liftM2 (+) [0,1] [0,2][0,2,1,3]
Example1 expression
liftM2 (+) (Just 1) NothingNothing
Example1 expression
liftM2 (+) (+ 3) (* 2) 518
methodliftA2 :: (a -> b -> c) -> f a -> f b -> f c
#

Lift a binary function to actions.

Some functors support an implementation of liftA2 that is more efficient than the default one. In particular, if fmap is an expensive operation, it is likely better to use liftA2 than to fmap over the structure and then use <*>.

This became a typeclass method in 4.10.0.0. Prior to that, it was a function defined in terms of <*> and fmap.

Example
Example1 expression
liftA2 (,) (Just 3) (Just 5)Just (3,5)
Example1 expression
liftA2 (+) [1, 2, 3] [4, 5, 6][5,6,7,6,7,8,7,8,9]
valueliftA3 :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
#

Lift a ternary function to actions.

valuevoid :: Functor f => f a -> f ()
#

void value discards or ignores the result of evaluation, such as the return value of an System.IO.IO action.

Examples

Replace the contents of a Maybe Int with unit:

Example1 expression
void NothingNothing
Example1 expression
void (Just 3)Just ()

Replace the contents of an Either Int Int with unit, resulting in an Either Int ():

Example1 expression
void (Left 8675309)Left 8675309
Example1 expression
void (Right 8675309)Right ()

Replace every element of a list with unit:

Example1 expression
void [1,2,3][(),(),()]

Replace the second element of a pair with unit:

Example1 expression
void (1,2)(1,())

Discard the result of an System.IO.IO action:

Example1 expression
mapM print [1,2]12[(),()]
Example1 expression
void $ mapM print [1,2]12
method(<>) :: a -> a -> a
#

An associative operation.

Examples
Example1 expression
[1,2,3] <> [4,5,6][1,2,3,4,5,6]
Example1 expression
Just [1, 2, 3] <> Just [4, 5, 6]Just [1,2,3,4,5,6]
Example1 expression
putStr "Hello, " <> putStrLn "World!"Hello, World!