-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | An alternative to monads in do-notation
--   
--   This "control-dsl" package is a toolkit to create extensible Domain
--   Specific Languages in <tt>do</tt>-notation.
--   
--   See <a>Control.Dsl</a> for more information.
@package control-dsl
@version 0.2.1.3

module Control.Dsl.PolyCont

-- | A use case of an <b>ad-hoc polymorphic delimited continuation</b>.
--   
--   Note that a <a>PolyCont</a> is not a <b>polymorphic delimited
--   continuation</b>, since a <a>PolyCont</a> does not support answer type
--   modification.
class PolyCont k r a

-- | Run as a CPS function .
runPolyCont :: PolyCont k r a => k r' a -> (a -> r) -> r

module Control.Dsl.Monadic

-- | This <tt>Monadic</tt> keyword extracts the monadic value of a monadic
--   expression.
newtype Monadic m r a
Monadic :: m a -> Monadic m r a
instance GHC.Base.Monad m => Control.Dsl.PolyCont.PolyCont (Control.Dsl.Monadic.Monadic m) (m b) a

module Control.Dsl.Empty
data Empty r a
[Empty] :: Empty r Void

-- | Return an empty <tt>a</tt>, similar to <a>empty</a>.
--   
--   This <a>empty</a> function aims to be used as the last statement of a
--   <tt>do</tt> block.
empty :: PolyCont Empty a Void => a
instance GHC.Base.Alternative m => Control.Dsl.PolyCont.PolyCont Control.Dsl.Empty.Empty (m a) Data.Void.Void

module Control.Dsl.Return
data Return r' r a
[Return] :: r' -> Return r' r Void

-- | Lift <tt>r</tt> to the answer type, similar to <a>return</a>.
--   
--   This <a>return</a> function aims to be used as the last statement of a
--   <tt>do</tt> block.
--   
--   When <a>return</a> is present in a nested <tt>do</tt> block for
--   <a>when</a> or <a>unless</a>, if the <tt>r'</tt> is not <tt>()</tt>,
--   it will create a <a>Cont</a> that performs early return, skipping the
--   rest statements of the outer <tt>do</tt> notation.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :set -XTypeOperators
--   
--   &gt;&gt;&gt; :set -XRebindableSyntax
--   
--   &gt;&gt;&gt; import Prelude hiding ((&gt;&gt;), (&gt;&gt;=), return, fail)
--   
--   &gt;&gt;&gt; import Control.Dsl
--   
--   &gt;&gt;&gt; import Control.Dsl.Return
--   
--   &gt;&gt;&gt; import Control.Dsl.Yield
--   
--   &gt;&gt;&gt; import Control.Dsl.Cont
--   
--   &gt;&gt;&gt; import Control.Dsl.Empty
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   earlyGenerator :: Bool -&gt; Cont [String] Integer
--   earlyGenerator earlyReturn = do
--     Yield "inside earlyGenerator"
--     when earlyReturn $ do
--       Yield "early return"
--       return 1
--     Yield "normal return"
--     return 0
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   earlyGeneratorTest :: [String]
--   earlyGeneratorTest = do
--     Yield "before earlyGenerator"
--     i &lt;- earlyGenerator True
--     Yield "after earlyGenerator"
--     Yield $ "the return value of earlyGenerator is " ++ show i
--     empty
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; earlyGeneratorTest
--   ["before earlyGenerator","inside earlyGenerator","early return","after earlyGenerator","the return value of earlyGenerator is 1"]
--   </pre>
return :: PolyCont (Return r') r Void => r' -> r

-- | Lift an <a>IOError</a> to the answer type, similar to <a>fail</a>.
--   
--   This <a>fail</a> function aims to be used as the last statement of a
--   <tt>do</tt> block.
fail :: PolyCont (Return IOError) r Void => String -> r
instance Control.Dsl.PolyCont.PolyCont (Control.Dsl.Return.Return r) r Data.Void.Void
instance GHC.Base.Applicative m => Control.Dsl.PolyCont.PolyCont (Control.Dsl.Return.Return r) (m r) Data.Void.Void

module Control.Dsl.Cont

-- | A type alias to <a>Cont</a> for a deeply nested delimited
--   continuation.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :set -XTypeOperators
--   
--   &gt;&gt;&gt; :set -XRebindableSyntax
--   
--   &gt;&gt;&gt; import Prelude hiding ((&gt;&gt;), (&gt;&gt;=), return, fail)
--   
--   &gt;&gt;&gt; import Control.Dsl
--   
--   &gt;&gt;&gt; import Control.Dsl.Yield
--   
--   &gt;&gt;&gt; import Control.Dsl.Empty
--   
--   &gt;&gt;&gt; import Control.Dsl.Monadic
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   f :: IO () !! [Integer] !! [String] !! [Double]
--   f = do
--     Yield "foo"
--     Yield 0.5
--     Yield "bar"
--     Yield 42
--     Yield "baz"
--     return ([] :: [Double])
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   f &gt;&gt;= (\d -&gt; do { Monadic $ putStrLn $ "double list: " ++ show d
--                   ; return ([] :: [String]) })
--     &gt;&gt;= (\s -&gt; do { Monadic $ putStrLn $ "string list: " ++ show s
--                   ; return ([] :: [Integer]) })
--     &gt;&gt;= (\i -&gt; do { Monadic $ putStrLn $ "integer list: " ++ show i
--                   ; return () })
--   :}
--   double list: [0.5]
--   string list: ["foo","bar","baz"]
--   integer list: [42]
--   </pre>
type (!!) = Cont

-- | A delimited continuation that can be used in a <tt>do</tt> block.
newtype Cont r a
Cont :: ((a -> r) -> r) -> Cont r a
[runCont] :: Cont r a -> (a -> r) -> r

-- | Convert a <a>PolyCont</a> to a <a>Cont</a>.
toCont :: PolyCont k r a => k r' a -> Cont r a
when :: Bool -> Cont r () -> Cont r ()
unless :: () => Bool -> Cont r () -> Cont r ()
guard :: PolyCont Empty r Void => Bool -> Cont r ()
instance Control.Dsl.PolyCont.PolyCont k r a => Control.Dsl.PolyCont.PolyCont k (Control.Dsl.Cont.Cont r a') a
instance Control.Dsl.PolyCont.PolyCont (Control.Dsl.Return.Return r) (Control.Dsl.Cont.Cont r' r) Data.Void.Void
instance Control.Dsl.PolyCont.PolyCont Control.Dsl.Empty.Empty r Data.Void.Void => Control.Dsl.PolyCont.PolyCont Control.Dsl.Empty.Empty (Control.Dsl.Cont.Cont r a) Data.Void.Void


module Control.Dsl.Shift

-- | A keyword to extract the value of a CPS function .
newtype Shift r' r a
Shift :: ((a -> r') -> r') -> Shift r' r a
instance Control.Dsl.PolyCont.PolyCont (Control.Dsl.Shift.Shift r) r a

module Control.Dsl.State.Put
data Put s r a
[Put] :: s -> Put s r ()
instance Control.Dsl.PolyCont.PolyCont (Control.Dsl.State.Put.Put s) (Control.Dsl.State.State.State s r) ()

module Control.Dsl.State.Get
data Get r a
[Get] :: forall s r. Get r s
instance Control.Dsl.PolyCont.PolyCont Control.Dsl.State.Get.Get (Control.Dsl.State.State.State s r) s


-- | This module provides keywords to <a>Put</a> and <a>Get</a> the value
--   on multiple mutable variables in a <tt>do</tt> block.
module Control.Dsl.State

-- | The type that holds states, which is defined as a plain function.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :set -XFlexibleContexts
--   
--   &gt;&gt;&gt; :set -XTypeApplications
--   
--   &gt;&gt;&gt; :set -XRebindableSyntax
--   
--   &gt;&gt;&gt; import Prelude hiding ((&gt;&gt;), (&gt;&gt;=), return, fail)
--   
--   &gt;&gt;&gt; import Control.Dsl
--   
--   &gt;&gt;&gt; import Control.Dsl.Cont
--   
--   &gt;&gt;&gt; import Control.Dsl.Shift
--   
--   &gt;&gt;&gt; import Control.Dsl.State
--   
--   &gt;&gt;&gt; import Data.Sequence (Seq, (|&gt;))
--   
--   &gt;&gt;&gt; import qualified Data.Sequence
--   
--   &gt;&gt;&gt; import Data.Foldable
--   </pre>
--   
--   The following <tt>append</tt> function <a>Get</a>s a <tt>Seq
--   String</tt> state, appends <tt>s</tt> to the <tt>Seq</tt>, and
--   <a>Put</a>s the new <tt>Seq</tt> as the updated state.
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   append s = do
--     buffer &lt;- Get @(Seq String)
--     toCont $ Put $ buffer |&gt; s
--   :}
--   </pre>
--   
--   <tt>append</tt> returns a <a>Cont</a>, which can be used in other
--   <tt>do</tt> blocks.
--   
--   A <tt>formatter</tt> <tt>append</tt>s <a>String</a> to its internal
--   buffer, and <a>return</a> the concatenated buffer.
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   formatter = do
--     append "x="
--     d &lt;- Get @Double
--     append $ show d
--     append ",y="
--     i &lt;- Get @Integer
--     append $ show i
--     buffer &lt;- Get @(Seq String)
--     return $ concat buffer
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; x = 0.5 :: Double
--   
--   &gt;&gt;&gt; y = 42 :: Integer
--   
--   &gt;&gt;&gt; initialBuffer = Data.Sequence.empty :: Seq String
--   
--   &gt;&gt;&gt; formatter x y initialBuffer :: String
--   "x=0.5,y=42"
--   </pre>
--   
--   Note that <tt>formatter</tt> accepts arbitrary order of the
--   parameters, or additional unused parameters.
--   
--   <pre>
--   &gt;&gt;&gt; formatter "unused parameter" initialBuffer y x :: String
--   "x=0.5,y=42"
--   </pre>
type State = (->)


-- | This module contains the <a>Yield</a> data type and related
--   <tt>Dsl</tt> instances.
--   
--   The <a>Yield</a> data type can be used to create generators, similar
--   to the <tt>yield</tt> keyword in C#, Python, and ECMAScript.
module Control.Dsl.Yield

-- | This <tt>Yield</tt> keyword produces an element in a list generator
--   
--   <h4><b>Examples</b></h4>
--   
--   <tt>randomGenerator</tt> is an example to create an xorshift
--   pseudo-random number generator that returns an infinite list of
--   generated numbers.
--   
--   <pre>
--   &gt;&gt;&gt; :set -XTypeApplications
--   
--   &gt;&gt;&gt; :set -XRebindableSyntax
--   
--   &gt;&gt;&gt; import Prelude hiding ((&gt;&gt;), (&gt;&gt;=), return, fail)
--   
--   &gt;&gt;&gt; import Control.Dsl
--   
--   &gt;&gt;&gt; import Data.Word
--   
--   &gt;&gt;&gt; import Data.Bits
--   
--   &gt;&gt;&gt; :{
--   randomGenerator :: Word32 -&gt; [Word32]
--   randomGenerator seed =
--     do let tmp1 = xor seed $ shiftL seed 13
--        let tmp2 = xor tmp1 $ shiftR tmp1 17
--        let tmp3 = xor tmp2 $ shiftL tmp2 5
--        Yield tmp3
--        randomGenerator tmp3
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; take 5 $ randomGenerator 2463534242
--   [723471715,2497366906,2064144800,2008045182,3532304609]
--   </pre>
data Yield x r a
[Yield] :: x -> Yield x r ()
instance Control.Dsl.PolyCont.PolyCont (Control.Dsl.Yield.Yield x) [x] ()
instance Control.Dsl.PolyCont.PolyCont (Control.Dsl.Yield.Yield x) (Control.Dsl.Cont.Cont r [x]) ()


-- | This <a>Control.Dsl</a> module and its submodules provide a toolkit to
--   create extensible Domain Specific Languages in <tt>do</tt>-notation.
--   
--   A DSL <tt>do</tt> block contains heterogeneous statements from
--   different vendors. A statement can be defined as a GADT, interpreted
--   by a <a>Dsl</a> type class instance, either effectfully or purely.
--   
--   A DSL <tt>do</tt> block is abstract. When creating the block, the type
--   class requirements is automatically inferred. Therefore, the data
--   structures and implementation of interpreters can be switched by
--   providing different instances.
--   
--   <h1>Getting started</h1>
--   
--   This package provides <a>Dsl</a> type class used in <tt>do</tt>
--   notation, as a replacement to <a>Monad</a>.
--   
--   <tt>RebindableSyntax</tt> extension is required to enable DSL
--   <tt>do</tt> notation.
--   
--   <pre>
--   &gt;&gt;&gt; :set -XRebindableSyntax
--   
--   &gt;&gt;&gt; import Prelude hiding ((&gt;&gt;), (&gt;&gt;=), return, fail)
--   
--   &gt;&gt;&gt; import Control.Dsl
--   </pre>
--   
--   <h2>DSL model</h2>
--   
--   Suppose you are creating a DSL for console IO, you need to define some
--   keywords allowed in the DSL.
--   
--   Each keyword is a GADT:
--   
--   <pre>
--   &gt;&gt;&gt; data MaxLengthConfig r a where MaxLengthConfig :: MaxLengthConfig r Int
--   
--   &gt;&gt;&gt; data GetLine r a where GetLine :: GetLine r String
--   
--   &gt;&gt;&gt; data PutStrLn r a where PutStrLn :: String -&gt; PutStrLn r ()
--   </pre>
--   
--   <h2>DSL <tt>do</tt> block</h2>
--   
--   Then those keywords can be used in <tt>do</tt> blocks:
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   dslBlock = do
--     maxLength &lt;- MaxLengthConfig
--     line1 &lt;- GetLine
--     line2 &lt;- GetLine
--     when (length line1 + length line2 &gt; maxLength) $ do
--       PutStrLn "The input is too long"
--       fail "Illegal input"
--     PutStrLn ("The input is " ++ line1 ++ " and " ++ line2)
--     return ()
--   :}
--   </pre>
--   
--   The above <tt>dslBlock</tt> function creates an abstract code block of
--   DSL from keywords and some built-in control flow functions.
--   
--   Keywords and the result statement <a>return</a> and <a>fail</a> are
--   ad-hoc polymorphic delimited continuations, interpreted by
--   <a>PolyCont</a>, which can be automatically inferred:
--   
--   <pre>
--   &gt;&gt;&gt; :type dslBlock
--   dslBlock
--     :: (PolyCont (Return IOError) r Void, PolyCont (Return ()) r Void,
--         PolyCont MaxLengthConfig r Int, PolyCont GetLine r [Char],
--         PolyCont PutStrLn r ()) =&gt;
--        r
--   </pre>
--   
--   <h3>Creating a pure interpreter</h3>
--   
--   The type <tt>r</tt> varies from different <a>PolyCont</a> instances.
--   By defining <a>PolyCont</a> instances for <tt>PureInterpreter</tt>,
--   you can make <tt>r</tt> be a pure interpreter:
--   
--   <pre>
--   &gt;&gt;&gt; type PureInterpreter = Int -&gt; [String] -&gt; Cont [String] IOError
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   instance PolyCont MaxLengthConfig PureInterpreter Int where
--     runPolyCont MaxLengthConfig = runPolyCont Get
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   instance PolyCont PutStrLn PureInterpreter () where
--     runPolyCont (PutStrLn s) = runPolyCont (Yield s)
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   instance PolyCont (Return ()) PureInterpreter Void where
--     runPolyCont (Return ()) = runPolyCont Empty
--   :}
--   </pre>
--   
--   The above three <a>PolyCont</a> instances are implemented as
--   forwarders to other existing keywords.
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   instance PolyCont GetLine PureInterpreter String where
--     runPolyCont k = runCont $ do
--       x : xs &lt;- Get @[String]
--       Put xs
--       return x
--   :}
--   ...
--   </pre>
--   
--   The <a>PolyCont</a> instance for <tt>GetLine</tt> is implemented as a
--   <a>Cont</a> that contains a DSL <tt>do</tt> block of atomic
--   statements.
--   
--   <h3>Running the DSL purely</h3>
--   
--   <pre>
--   &gt;&gt;&gt; runPurely = dslBlock :: PureInterpreter
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; errorHandler e = ["(handled) " ++ show e]
--   
--   &gt;&gt;&gt; runCont (runPurely 80 ["LINE_1", "LINE_2"]) errorHandler
--   ["The input is LINE_1 and LINE_2"]
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; longInput = [replicate 40 '*', replicate 41 '*']
--   
--   &gt;&gt;&gt; runCont (runPurely 80 longInput) errorHandler
--   ["The input is too long","(handled) user error (Illegal input)"]
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; runCont (runPurely 80 ["ONE_LINE"]) errorHandler
--   ["(handled) user error (Pattern match failure in do expression at &lt;interactive&gt;..."]
--   </pre>
--   
--   <h3>Creating an effectful interpreter</h3>
--   
--   Alternatively, <tt>dslBlock</tt> can run effectfully by providing
--   effectful <a>PolyCont</a> instances.
--   
--   <pre>
--   &gt;&gt;&gt; type EffectfulInterpreter = Handle -&gt; IO ()
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   instance PolyCont GetLine EffectfulInterpreter String where
--     runPolyCont GetLine = runCont $ do
--       h &lt;- Get
--       line &lt;- Monadic (hGetLine h)
--       return line
--   :}
--   </pre>
--   
--   <a>Monadic</a> is a built-in keyword to perform old-fashioned monadic
--   action in a DSL <tt>do</tt> block.
--   
--   Other keywords can be used together with <a>Monadic</a>. No monad
--   transformer is required.
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   instance PolyCont MaxLengthConfig (IO ()) Int where
--     runPolyCont MaxLengthConfig f = f 80
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   instance PolyCont PutStrLn (IO ()) () where
--     runPolyCont (PutStrLn s) = (Prelude.&gt;&gt;=) (putStrLn s)
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   instance PolyCont (Return IOError) (IO ()) Void where
--     runPolyCont (Return e) _ = hPutStrLn stderr (show e)
--   :}
--   </pre>
--   
--   The above three <a>PolyCont</a> instances are not directly implemented
--   for <tt>EffectfulInterpreter</tt>. Instead, they are implemented for
--   <tt>IO ()</tt>. Then, instances for <tt>EffectfulInterpreter</tt> can
--   be automatically derived from instances for <tt>IO ()</tt>. There are
--   two built-in <a>PolyCont</a> derivation rules, for <a>Cont</a> and
--   <a>State</a>, respectively. What interesting is that <a>State</a> is
--   defined as plain function, which exactly matches the type of
--   <tt>EffectfulInterpreter</tt>.
--   
--   <h3>Running the DSL effectfully</h3>
--   
--   <pre>
--   &gt;&gt;&gt; runEffectfully = dslBlock :: EffectfulInterpreter
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   withSystemTempFile "tmp-input-file" $ \_ -&gt; \h -&gt; do
--     Monadic $ hPutStrLn h "LINE_1"
--     Monadic $ hPutStrLn h "LINE_2"
--     Monadic $ hSeek h AbsoluteSeek 0
--     runEffectfully h
--   :}
--   The input is LINE_1 and LINE_2
--   </pre>
module Control.Dsl

-- | Witnesses a use case of a statement in a <tt>do</tt> block.
--   
--   <h2>Allowed statements in DSL <tt>do</tt> blocks</h2>
--   
--   Statements in a DSL <tt>do</tt> block are delimited continuations
--   (except the last statement), which can be either ad-hoc polymorphic
--   GADT keywords, or monomorphic control flow operators.
--   
--   The last statement is the final result of the <tt>do</tt> block, or
--   the <i>answer type</i> of other delimited continuation statements.
--   
--   TODO: table
--   
--   Don't create custom instances of <a>Dsl</a> for statement. Instead,
--   create <a>PolyCont</a> instances for your custom GADT keywords.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :set -XGADTs
--   
--   &gt;&gt;&gt; :set -XMultiParamTypeClasses
--   
--   &gt;&gt;&gt; :set -XFlexibleInstances
--   
--   &gt;&gt;&gt; :set -XFlexibleContexts
--   
--   &gt;&gt;&gt; :set -XRebindableSyntax
--   
--   &gt;&gt;&gt; :set -XTypeApplications
--   
--   &gt;&gt;&gt; import qualified Prelude
--   
--   &gt;&gt;&gt; import Prelude hiding ((&gt;&gt;), (&gt;&gt;=), return, fail)
--   
--   &gt;&gt;&gt; import Control.Dsl
--   
--   &gt;&gt;&gt; import Control.Dsl.State.Get
--   
--   &gt;&gt;&gt; import Control.Dsl.Yield
--   
--   &gt;&gt;&gt; import Control.Dsl.Return
--   
--   &gt;&gt;&gt; import Data.Void
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   f = do
--     Yield "foo"
--     config &lt;- Get @Bool
--     when config $ do
--       Yield "bar"
--       return ()
--     return "baz"
--   :}
--   </pre>
--   
--   <tt>f</tt> is a <tt>do</tt> block that contains keywords of
--   <a>Get</a>, <a>Yield</a>, and <a>return</a>. With the help of built-in
--   <a>PolyCont</a> instances for those keywords, <tt>f</tt> can be used
--   as a function that accepts a boolean parameter.
--   
--   <pre>
--   &gt;&gt;&gt; f False :: [String]
--   ["foo","baz"]
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; f True :: [String]
--   ["foo","bar","baz"]
--   </pre>
--   
--   In fact, <tt>f</tt> can be any type as long as <a>PolyCont</a>
--   instances for involved keywords are provided.
--   
--   <pre>
--   &gt;&gt;&gt; :type f
--   f :: (PolyCont (Yield [Char]) r (),
--         PolyCont (Return [Char]) r Void, PolyCont Get r Bool) =&gt;
--        r
--   </pre>
--   
--   For example, <tt>f</tt> can be interpreted as an impure <tt>IO
--   ()</tt>, providing the following instances:
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   instance PolyCont (Yield String) (IO ()) () where
--     runPolyCont (Yield a) = (Prelude.&gt;&gt;=) (putStrLn $ "Yield " ++ a)
--   instance PolyCont Get (IO ()) Bool where
--     runPolyCont Get f = putStrLn "Get" Prelude.&gt;&gt; f False
--   instance PolyCont (Return String) (IO ()) Void where
--     runPolyCont (Return r) _ = putStrLn $ "Return " ++ r
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; f :: IO ()
--   Yield foo
--   Get
--   Return baz
--   </pre>
class Dsl k r a

-- | The implementation of <tt>&lt;-</tt> statements in a <tt>do</tt>
--   block, which forwards to <a>runCont</a> if <tt>k</tt> is <a>Cont</a>,
--   otherwise forwards to <a>runPolyCont</a> from <a>PolyCont</a>.
(>>=) :: Dsl k r a => k r a -> (a -> r) -> r
(=<<) :: Dsl k r a => (a -> r) -> k r a -> r
(>=>) :: Dsl k r a => (t -> k r a) -> (a -> r) -> t -> r
(<=<) :: Dsl k r a => (a -> r) -> (t -> k r a) -> t -> r

-- | The implementation of statements with no value in a <tt>do</tt> block.
(>>) :: Dsl k r b => k r b -> r -> r
forever :: Dsl k r a => k r a -> r
ifThenElse :: () => Bool -> p -> p -> p

-- | Lift <tt>r</tt> to the answer type, similar to <a>return</a>.
--   
--   This <a>return</a> function aims to be used as the last statement of a
--   <tt>do</tt> block.
--   
--   When <a>return</a> is present in a nested <tt>do</tt> block for
--   <a>when</a> or <a>unless</a>, if the <tt>r'</tt> is not <tt>()</tt>,
--   it will create a <a>Cont</a> that performs early return, skipping the
--   rest statements of the outer <tt>do</tt> notation.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; :set -XTypeOperators
--   
--   &gt;&gt;&gt; :set -XRebindableSyntax
--   
--   &gt;&gt;&gt; import Prelude hiding ((&gt;&gt;), (&gt;&gt;=), return, fail)
--   
--   &gt;&gt;&gt; import Control.Dsl
--   
--   &gt;&gt;&gt; import Control.Dsl.Return
--   
--   &gt;&gt;&gt; import Control.Dsl.Yield
--   
--   &gt;&gt;&gt; import Control.Dsl.Cont
--   
--   &gt;&gt;&gt; import Control.Dsl.Empty
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   earlyGenerator :: Bool -&gt; Cont [String] Integer
--   earlyGenerator earlyReturn = do
--     Yield "inside earlyGenerator"
--     when earlyReturn $ do
--       Yield "early return"
--       return 1
--     Yield "normal return"
--     return 0
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; :{
--   earlyGeneratorTest :: [String]
--   earlyGeneratorTest = do
--     Yield "before earlyGenerator"
--     i &lt;- earlyGenerator True
--     Yield "after earlyGenerator"
--     Yield $ "the return value of earlyGenerator is " ++ show i
--     empty
--   :}
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; earlyGeneratorTest
--   ["before earlyGenerator","inside earlyGenerator","early return","after earlyGenerator","the return value of earlyGenerator is 1"]
--   </pre>
return :: PolyCont (Return r') r Void => r' -> r

-- | Lift an <a>IOError</a> to the answer type, similar to <a>fail</a>.
--   
--   This <a>fail</a> function aims to be used as the last statement of a
--   <tt>do</tt> block.
fail :: PolyCont (Return IOError) r Void => String -> r
when :: Bool -> Cont r () -> Cont r ()
unless :: () => Bool -> Cont r () -> Cont r ()
guard :: PolyCont Empty r Void => Bool -> Cont r ()
