arrows-0.4.4.2: Control/Arrow/Internals.hs
-----------------------------------------------------------------------------
-- |
-- Module : Control.Arrow.Internals
-- Copyright : (c) Ross Paterson 2003
-- License : BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer : ross@soi.city.ac.uk
-- Stability : experimental
-- Portability : non-portable (multi-parameter type classes)
--
-- Manipulation of composite arrow types, beyond the basic lifting and
-- encapsulation provided with each arrow transformer.
--
-- The signatures are designed to be compatible with the proposed notation
-- for arrows, cf. <http://www.haskell.org/arrows/>.
-- #hide
module Control.Arrow.Internals (
ArrowAddState(..),
ArrowAddReader(..),
ArrowAddWriter(..),
ArrowAddError(..),
ArrowAddStream(..),
) where
import Control.Arrow
import Control.Arrow.Operations
import Data.Stream
-- | Adding a 'Control.Arrow.Transformer.State.StateArrow' to an
-- arrow type, but not necessarily as the outer arrow transformer.
--
-- Typically a composite arrow type is built by applying a series
-- of arrow transformer to a base arrow (usually either a function
-- arrow or a 'Kleisli' arrow. One can add a transformer to the
-- top of this stack using the 'Control.Arrow.Transformer.lift'
-- method of the 'Control.Arrow.Transformer.ArrowTransformer' class,
-- or remove a state transformer from the top of the stack using the
-- 'Control.Arrow.Transformer.State.runState' encapsulation operator.
-- The methods of this class add and remove state transformers anywhere
-- in the stack. In the instance
--
-- > instance Arrow a => ArrowAddState s (ArrowState s a) a
--
-- they are equivalent to 'Control.Arrow.Transformer.lift' and
-- 'Control.Arrow.Transformer.State.runState' respectively.
-- Instances are lifted through other transformers with
--
-- > instance ArrowAddState s a a' =>
-- > ArrowAddState s (FooArrow a) (FooArrow a')
class (ArrowState s a, Arrow a') => ArrowAddState s a a' | a -> a' where
-- | Lift a computation from an arrow to one with an added state.
--
-- Typical usage in arrow notation:
--
-- > proc p -> ...
-- > (|liftState cmd|)
liftState :: a' e b -> a e b
-- | Elimination of a state transformer from a computation,
-- exposing the initial and final states.
--
-- Typical usage in arrow notation:
--
-- > proc p -> do
-- > ...
-- > (result, final_state) <- (|elimState cmd|) init_state
elimState :: a e b -> a' (e,s) (b,s)
-- | Adding a 'Control.Arrow.Transformer.Reader.ReaderArrow' to an
-- arrow type, but not necessarily as the outer arrow transformer.
--
-- Typically a composite arrow type is built by applying a series
-- of arrow transformer to a base arrow (usually either a function
-- arrow or a 'Kleisli' arrow. One can add a transformer to the
-- top of this stack using the 'Control.Arrow.Transformer.lift'
-- method of the 'Control.Arrow.Transformer.ArrowTransformer' class,
-- or remove a state transformer from the top of the stack using the
-- 'Control.Arrow.Transformer.Reader.runReader' encapsulation operator.
-- The methods of this class add and remove state transformers anywhere
-- in the stack. In the instance
--
-- > instance Arrow a => ArrowAddReader r (ArrowReader r a) a
--
-- they are equivalent to 'Control.Arrow.Transformer.lift' and
-- 'Control.Arrow.Transformer.Reader.runReader' respectively.
-- Instances are lifted through other transformers with
--
-- > instance ArrowAddReader r a a' =>
-- > ArrowAddReader r (FooArrow a) (FooArrow a')
class (ArrowReader r a, Arrow a') => ArrowAddReader r a a' | a -> a' where
-- | Lift a computation from an arrow to one with an added environment.
--
-- Typical usage in arrow notation:
--
-- > proc p -> ...
-- > (|liftReader cmd|)
liftReader :: a' e b -> a e b
-- | Elimination of a state reader from a computation,
-- taking a value for the state.
--
-- Typical usage in arrow notation:
--
-- > proc p -> ...
-- > (|elimReader cmd|) env
elimReader :: a e b -> a' (e,r) b
-- | Adding a 'Control.Arrow.Transformer.Writer.WriterArrow' to an
-- arrow type, but not necessarily as the outer arrow transformer.
--
-- Typically a composite arrow type is built by applying a series
-- of arrow transformer to a base arrow (usually either a function
-- arrow or a 'Kleisli' arrow. One can add a transformer to the
-- top of this stack using the 'Control.Arrow.Transformer.lift'
-- method of the 'Control.Arrow.Transformer.ArrowTransformer' class,
-- or remove a state transformer from the top of the stack using the
-- 'Control.Arrow.Transformer.Writer.runWriter' encapsulation operator.
-- The methods of this class add and remove state transformers anywhere
-- in the stack. In the instance
--
-- > instance Arrow a => ArrowAddWriter w (ArrowWriter w a) a
--
-- they are equivalent to 'Control.Arrow.Transformer.lift' and
-- 'Control.Arrow.Transformer.Writer.runWriter' respectively.
-- Instances are lifted through other transformers with
--
-- > instance ArrowAddWriter w a a' =>
-- > ArrowAddWriter w (FooArrow a) (FooArrow a')
class (ArrowWriter w a, Arrow a') => ArrowAddWriter w a a' | a -> a' where
-- | Lift a computation from an arrow to one with added output.
--
-- Typical usage in arrow notation:
--
-- > proc p -> ...
-- > (|liftWriter cmd|)
liftWriter :: a' e b -> a e b
-- | Elimination of an output writer from a computation,
-- providing the accumulated output.
--
-- Typical usage in arrow notation:
--
-- > proc p -> do
-- > ...
-- > (result, output) <- (|elimWriter cmd|)
elimWriter :: a e b -> a' e (b,w)
-- | Adding a 'Control.Arrow.Transformer.Error.ErrorArrow' to an
-- arrow type, but not necessarily as the outer arrow transformer.
--
-- Typically a composite arrow type is built by applying a series
-- of arrow transformer to a base arrow (usually either a function
-- arrow or a 'Kleisli' arrow. One can add a transformer to the
-- top of this stack using the 'Control.Arrow.Transformer.lift'
-- method of the 'Control.Arrow.Transformer.ArrowTransformer' class,
-- or remove a state transformer from the top of the stack using the
-- 'Control.Arrow.Transformer.Error.runError' encapsulation operator.
-- The methods of this class add and remove state transformers anywhere
-- in the stack. In the instance
--
-- > instance Arrow a => ArrowAddError ex (ArrowError ex a) a
--
-- they are equivalent to 'Control.Arrow.Transformer.lift' and
-- 'Control.Arrow.Transformer.Error.runError' respectively.
-- Instances are lifted through other transformers with
--
-- > instance ArrowAddError ex a a' =>
-- > ArrowAddError ex (FooArrow a) (FooArrow a')
--
-- This could be combined with 'Control.Arrow.Transformer.Error.handle',
-- since the resulting arrow is always the arrow of the handler.
-- Separating them has the advantage of consistency with the other arrows,
-- and might give more helpful type error messages.
class (ArrowError ex a, Arrow a') => ArrowAddError ex a a' | a -> a' where
-- | Lift a computation from an arrow to one with error handling.
--
-- Typical usage in arrow notation:
--
-- > proc p -> ...
-- > (|liftError cmd|)
liftError :: a' e b -> a e b
-- | Elimination of errors from a computation,
-- by completely handling any errors.
--
-- Typical usage in arrow notation:
--
-- > proc p -> ...
-- > body `elimError` \ex -> handler
elimError :: a e b -> a' (e,ex) b -> a' e b
-- | Adding a 'Control.Arrow.Transformer.Stream.StreamArrow' to an
-- arrow type, but not necessarily as the outer arrow transformer.
--
-- Typically a composite arrow type is built by applying a series
-- of arrow transformer to a base arrow (usually either a function
-- arrow or a 'Kleisli' arrow. One can add a transformer to the
-- top of this stack using the 'Control.Arrow.Transformer.lift'
-- method of the 'Control.Arrow.Transformer.ArrowTransformer' class,
-- or remove a state transformer from the top of the stack using the
-- 'Control.Arrow.Transformer.Stream.runStream' encapsulation operator.
-- The methods of this class add and remove state transformers anywhere
-- in the stack. In the instance
--
-- > instance Arrow a => ArrowAddStream (ArrowStream a) a
--
-- they are equivalent to 'Control.Arrow.Transformer.lift' and
-- 'Control.Arrow.Transformer.Stream.runStream' respectively.
-- Instances are lifted through other transformers with
--
-- > instance ArrowAddStream a a' =>
-- > ArrowAddStream (FooArrow a) (FooArrow a')
class (ArrowCircuit a, Arrow a') => ArrowAddStream a a' | a -> a' where
-- | Lift a computation from an arrow to a stream processing one.
--
-- Typical usage in arrow notation:
--
-- > proc p -> ...
-- > (|liftStream cmd|)
liftStream :: a' e b -> a e b
-- | Run a stream processor on a stream of inputs,
-- obtaining a stream of outputs.
--
-- Typical usage in arrow notation:
--
-- > proc p -> do
-- > ...
-- > ys <- (|elimStream (\x -> ...)|) xs
--
-- Here @xs@ refers to the input stream and @x@ to individual
-- elements of that stream. @ys@ is bound to the output stream.
elimStream :: a (e,b) c -> a' (e,Stream b) (Stream c)