capability-0.4.0.0: Extensional capabilities and deriving combinators
Safe HaskellNone
LanguageHaskell2010

Capability.Sink

Description

Defines a capability for computations that produce a stream of values as part of their execution.

Programs producing streams of data are common. Examples: emitting events on input, or emitting events whenever certain conditions are observed. streams are similar to Python generators.

The HasSink capability enables separating the logic responsible for emitting events from that responsible for collecting or handling them. The name is because a sink is needed to consume the locally produced stream.

This can be thought of as a writer capability of a list of values HasWriter tag [v] with \x -> tell @tag [x] as a primitive operation. However, that implementation would be inefficient.

For example using the Stream instance, a producer defined using this capability can be consumed efficiently in a streaming fashion.

Synopsis

Relational capability

class Monad m => HasSink (tag :: k) (a :: Type) (m :: Type -> Type) | tag m -> a where Source #

Sinking capability.

An instance does not need to fulfill any additional laws besides the monad laws.

Methods

yield_ :: Proxy# tag -> a -> m () Source #

For technical reasons, this method needs an extra proxy argument. You only need it if you are defining new instances of HasSink. Otherwise, you will want to use yield. See yield for more documentation.

Instances

Instances details
(MutableRef ref, RefElement ref ~ s, HasSource tag ref m, PrimMonad m, PrimState m ~ MCState ref) => HasSink (tag :: k) s (ReaderRef m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> s -> ReaderRef m () Source #

MonadState s m => HasSink (tag :: k) s (MonadState m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> s -> MonadState m () Source #

(HasSink tag a m, MonadTrans t, Monad (t m)) => HasSink (tag :: k) a (Lift (t m)) Source #

Lift one layer in a monad transformer stack.

Note, that if the HasSink instance is based on HasState, then it is more efficient to apply Lift to the underlying state capability. E.g. you should favour

deriving (HasSink tag w) via
  SinkLog (Lift (SomeTrans (MonadState SomeStateMonad)))

over

deriving (HasSink tag w) via
  Lift (SomeTrans (SinkLog (MonadState SomeStateMonad)))
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> a -> Lift (t m) () Source #

HasState tag [a] m => HasSink (tag :: k) a (SinkStack m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> a -> SinkStack m () Source #

HasSink tag (DList a) m => HasSink (tag :: k) a (SinkDList m) Source #

This instance may seem a bit odd at first. All it does is wrap each yielded value in a single element difference list. How does re-yielding something else constitute a strategy for implementing HasSink in the first place? The answer is that difference lists form a monoid, which allows a second stragegy to be used which accumulates all yields in a single value, actually eliminating the HasSink constraint this time.

SinkLog below in fact does this, so the easiest way to fully eliminate the HasSink constraint as described above is:

deriving (HasSink tag w) via
  SinkDList (SinkLog (MonadState SomeStateMonad))
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> a -> SinkDList m () Source #

(Monoid w, HasState tag w m) => HasSink (tag :: k) w (SinkLog m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> w -> SinkLog m () Source #

(HasSource tag (IORef s) m, MonadIO m) => HasSink (tag :: k) s (ReaderIORef m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> s -> ReaderIORef m () Source #

(Coercible from to, HasSink tag from m) => HasSink (tag :: k) to (Coerce to m) Source #

Convert the state using safe coercion.

Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> to -> Coerce to m () Source #

Monad m => HasSink (tag :: k) a (Stream (Of a) m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> a -> Stream (Of a) m () Source #

(Monad m, Reifies s (Reified tag (HasSink tag a) m)) => HasSink (tag :: k) a (Reflected s (HasSink tag a) m) Source # 
Instance details

Defined in Capability.Sink.Internal.Class

Methods

yield_ :: Proxy# tag -> a -> Reflected s (HasSink tag a) m () Source #

(Monad m, Reifies s' (Reified tag (HasState tag s) m)) => HasSink (tag :: k) s (Reflected s' (HasState tag s) m) Source # 
Instance details

Defined in Capability.State.Internal.Class

Methods

yield_ :: Proxy# tag -> s -> Reflected s' (HasState tag s) m () Source #

HasSink oldtag s m => HasSink (newtag :: k2) s (Rename oldtag m) Source #

Rename the tag.

Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# newtag -> s -> Rename oldtag m () Source #

(forall x. Coercible (m x) (t2 (t1 m) x), Monad m, HasSink tag a (t2 (t1 m))) => HasSink (tag :: k) a ((t2 :.: t1) m) Source #

Compose two accessors.

Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> a -> (t2 :.: t1) m () Source #

(Monoid w, Monad m, Reifies s (Reified tag (HasWriter tag w) m)) => HasSink (tag :: k) w (Reflected s (HasWriter tag w) m) Source # 
Instance details

Defined in Capability.Writer

Methods

yield_ :: Proxy# tag -> w -> Reflected s (HasWriter tag w) m () Source #

(tag ~ pos, HasPosition' pos struct v, HasState oldtag struct m) => HasSink (tag :: Nat) v (Pos pos oldtag m) Source #

Zoom in on the field at position pos of type v in the state struct.

Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> v -> Pos pos oldtag m () Source #

(tag ~ field, HasField' field record v, HasState oldtag record m) => HasSink (tag :: Symbol) v (Field field oldtag m) Source #

Zoom in on the record field field of type v in the state record.

Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> v -> Field field oldtag m () Source #

data Reified (tag :: k) (HasSink tag a) m Source # 
Instance details

Defined in Capability.Sink.Internal.Class

data Reified (tag :: k) (HasSink tag a) m = ReifiedSink {}

yield :: forall tag a m. HasSink tag a m => a -> m () Source #

yield @tag a emits a in the sink capability tag.

Functional capability

type HasSink' (tag :: k) = HasSink tag (TypeOf k tag) Source #

Type synonym using the TypeOf type family to specify HasSink constraints without having to specify the type associated to a tag.

type family TypeOf k (s :: k) :: Type Source #

Type family associating a tag to the corresponding type. It is intended to simplify constraint declarations, by removing the need to redundantly specify the type associated to a tag.

It is poly-kinded, which allows users to define their own kind of tags. Standard haskell types can also be used as tags by specifying the Type kind when defining the type family instance.

Defining TypeOf instances for Symbols (typelevel string literals) is discouraged. Since symbols all belong to the same global namespace, such instances could conflict with others defined in external libraries. More generally, as for typeclasses, TypeOf instances should always be defined in the same module as the tag type to prevent issues due to orphan instances.

Example:

    import Capability.Reader

    data Foo
    data Bar
    type instance TypeOf Type Foo = Int
    type instance TypeOf Type Bar = String

    -- Same as: foo :: HasReader Foo Int M => …
    foo :: HasReader' Foo m => …
    foo = …

Strategies

newtype SinkStack m (a :: Type) Source #

Accumulate sunk values in a reverse order list.

Constructors

SinkStack (m a) 

Instances

Instances details
HasState tag [a] m => HasSink (tag :: k) a (SinkStack m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> a -> SinkStack m () Source #

Monad m => Monad (SinkStack m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

(>>=) :: SinkStack m a -> (a -> SinkStack m b) -> SinkStack m b #

(>>) :: SinkStack m a -> SinkStack m b -> SinkStack m b #

return :: a -> SinkStack m a #

Functor m => Functor (SinkStack m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

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

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

Applicative m => Applicative (SinkStack m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

pure :: a -> SinkStack m a #

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

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

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

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

MonadIO m => MonadIO (SinkStack m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

liftIO :: IO a -> SinkStack m a #

PrimMonad m => PrimMonad (SinkStack m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Associated Types

type PrimState (SinkStack m) #

Methods

primitive :: (State# (PrimState (SinkStack m)) -> (# State# (PrimState (SinkStack m)), a #)) -> SinkStack m a #

type PrimState (SinkStack m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

newtype SinkDList m (a :: Type) Source #

Accumulate sunk values in forward order in a difference list.

Constructors

SinkDList (m a) 

Instances

Instances details
HasSink tag (DList a) m => HasSink (tag :: k) a (SinkDList m) Source #

This instance may seem a bit odd at first. All it does is wrap each yielded value in a single element difference list. How does re-yielding something else constitute a strategy for implementing HasSink in the first place? The answer is that difference lists form a monoid, which allows a second stragegy to be used which accumulates all yields in a single value, actually eliminating the HasSink constraint this time.

SinkLog below in fact does this, so the easiest way to fully eliminate the HasSink constraint as described above is:

deriving (HasSink tag w) via
  SinkDList (SinkLog (MonadState SomeStateMonad))
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> a -> SinkDList m () Source #

Monad m => Monad (SinkDList m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

(>>=) :: SinkDList m a -> (a -> SinkDList m b) -> SinkDList m b #

(>>) :: SinkDList m a -> SinkDList m b -> SinkDList m b #

return :: a -> SinkDList m a #

Functor m => Functor (SinkDList m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

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

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

Applicative m => Applicative (SinkDList m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

pure :: a -> SinkDList m a #

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

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

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

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

MonadIO m => MonadIO (SinkDList m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

liftIO :: IO a -> SinkDList m a #

PrimMonad m => PrimMonad (SinkDList m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Associated Types

type PrimState (SinkDList m) #

Methods

primitive :: (State# (PrimState (SinkDList m)) -> (# State# (PrimState (SinkDList m)), a #)) -> SinkDList m a #

type PrimState (SinkDList m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

newtype SinkLog m (a :: Type) Source #

Accumulate sunk values with their own monoid.

Constructors

SinkLog (m a) 

Instances

Instances details
(Monoid w, HasState tag w m) => HasSink (tag :: k) w (SinkLog m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> w -> SinkLog m () Source #

(Monoid w, HasState tag w m) => HasWriter (tag :: k) w (WriterLog m) Source # 
Instance details

Defined in Capability.Writer

Methods

writer_ :: Proxy# tag -> (a, w) -> WriterLog m a Source #

listen_ :: Proxy# tag -> WriterLog m a -> WriterLog m (a, w) Source #

pass_ :: Proxy# tag -> WriterLog m (a, w -> w) -> WriterLog m a Source #

Monad m => Monad (SinkLog m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

(>>=) :: SinkLog m a -> (a -> SinkLog m b) -> SinkLog m b #

(>>) :: SinkLog m a -> SinkLog m b -> SinkLog m b #

return :: a -> SinkLog m a #

Functor m => Functor (SinkLog m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

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

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

Applicative m => Applicative (SinkLog m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

pure :: a -> SinkLog m a #

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

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

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

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

MonadIO m => MonadIO (SinkLog m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

liftIO :: IO a -> SinkLog m a #

PrimMonad m => PrimMonad (SinkLog m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Associated Types

type PrimState (SinkLog m) #

Methods

primitive :: (State# (PrimState (SinkLog m)) -> (# State# (PrimState (SinkLog m)), a #)) -> SinkLog m a #

type PrimState (SinkLog m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Modifiers