úÎ!†bƒ‚/      !"#$% & ' ( ) * + , - . Safe*;=>?STi control-dslA use case of an )ad-hoc polymorphic delimited continuation. Note that a  is not a "polymorphic delimited continuation , since a + does not support answer type modification. control-dslRun as a CPS function .Safe*;=>?4 control-dslThis Monadic< keyword extracts the monadic value of a monadic expression.Safe&';<=>? ¡ control-dslReturn an empty a , similar to  .This 5 function aims to be used as the last statement of a do block.Safe &'*;<=>?STÚ  control-dslLift r to the answer type, similar to .This  5 function aims to be used as the last statement of a do block.When   is present in a nested do block for when or unless , if the r is not (), it will create a ContG that performs early return, skipping the rest statements of the outer do notation.Examples:set -XTypeOperators:set -XRebindableSyntax1import Prelude hiding ((>>), (>>=), return, fail)import Control.Dslimport Control.Dsl.Returnimport Control.Dsl.Yieldimport Control.Dsl.Contimport Control.Dsl.Empty:{ /earlyGenerator :: Bool -> Cont [String] IntegerearlyGenerator earlyReturn = do Yield "inside earlyGenerator" when earlyReturn $ do Yield "early return" return 1 Yield "normal return" return 0:}:{earlyGeneratorTest :: [String]earlyGeneratorTest = do Yield "before earlyGenerator" i <- earlyGenerator True Yield "after earlyGenerator"< Yield $ "the return value of earlyGenerator is " ++ show i empty:}earlyGeneratorTest["before earlyGenerator","inside earlyGenerator","early return","after earlyGenerator","the return value of earlyGenerator is 1"]  control-dslLift an / to the answer type, similar to .This  5 function aims to be used as the last statement of a do block.  Safe &'*;<=>?ST$ü control-dslA type alias to , for a deeply nested delimited continuation.Examples:set -XTypeOperators:set -XRebindableSyntax1import Prelude hiding ((>>), (>>=), return, fail)import Control.Dslimport Control.Dsl.Yieldimport Control.Dsl.Empty:{/f :: IO () !! [Integer] !! [String] !! [Double]f = do Yield "foo" Yield 0.5 Yield 42 empty:}Safe*;=>?ST_£ control-dsl)Witnesses a use case of a statement in a do block.Allowed statements in DSL do blocksStatements in a DSL dou block is a delimited continuation (except the last statement), which can be a GADT keyword, a control flow operator..The last statement is the final result of the do block, or the  answer type, of other delimited continuation statements. Ç Keywords ) Control flow operators ^ Results  Examples  ,  ,  ,  , , ,    , , ,   , ,  ,   Type Ç custom GADT   6 the answer type r%  Interpreted by T T ) N/A    Can be present at ‚ not the last statement of a dok block 6 the last statement of a do$ block !Don't create custom instances of  for statement. Instead, create ) instances for your custom GADT keywords.Examples :set -XGADTs:set -XMultiParamTypeClasses:set -XFlexibleInstances:set -XFlexibleContexts:set -XRebindableSyntax:set -XTypeApplicationsimport qualified Prelude1import Prelude hiding ((>>), (>>=), return, fail)import Control.Dslimport Control.Dsl.State.Getimport Control.Dsl.Yieldimport Control.Dsl.Returnimport Data.Void:{f = do Yield "foo" config <- Get @Bool when config $ do Yield "bar" return () return "baz":}f is a do! block that contains keywords of  ,  , and . With the help of built-in  instances for those keywords, f< can be used as a function that accepts a boolean parameter.f False :: [String] ["foo","baz"]f True :: [String]["foo","bar","baz"] In fact, f can be any type as long as . instances for involved keywords are provided.:type f#f :: (PolyCont (Yield [Char]) r (),> PolyCont (Return [Char]) r Void, PolyCont Get r Bool) => r For example, f! can be interpreted as an impure IO ()$, providing the following instances::{1instance PolyCont (Yield String) (IO ()) () whereB runPolyCont (Yield a) = (Prelude.>>=) (putStrLn $ "Yield " ++ a)(instance PolyCont Get (IO ()) Bool where7 runPolyCont Get f = putStrLn "Get" Prelude.>> f False4instance PolyCont (Return String) (IO ()) Void where6 runPolyCont (Return r) _ = putStrLn $ "Return " ++ r:} f :: IO () Yield fooGet Return baz control-dslThe implementation of <- statements in a do block, which forwards to  if k is , otherwise forwards to  from . control-dsl4The implementation of statements with no value in a do block.0 control-dsl8Statements based on monomorphic delimited continuations.1 control-dsl?Statements based on ad-hoc polymorphic delimited continuations. 2 Delimited continuationsSafe;<=>?a‚! control-dsl2A keyword to extract the value of a CPS function .!"!"Safe &'*;<=>?QVu:$ control-dslAThe type that holds states, which is defined as a plain function.Examples :set -XFlexibleContexts:set -XTypeApplications:set -XRebindableSyntax1import Prelude hiding ((>>), (>>=), return, fail)import Control.Dslimport Control.Dsl.Contimport Control.Dsl.Shiftimport Control.Dsl.State import Data.Sequence (Seq, (|>))import qualified Data.Sequenceimport Data.FoldableThe following append function s a  Seq String state, appends s to the , and  s the new  to the updated state.:{ append s = do buffer <- Get @(Seq String) Put $ buffer |> s Cont ($ ()):}($ ())9 creates a CPS function , which can be then converted to s.A  formatter appends 3 to its internal buffer, and  the concatenated buffer.:{ formatter = do append "x=" d <- Get @Double append $ show d append ",y=" i <- Get @Integer append $ show i buffer <- Get @(Seq String) return $ concat buffer:}x = 0.5 :: Doubley = 42 :: Integer1initialBuffer = Data.Sequence.empty :: Seq String%formatter x y initialBuffer :: String "x=0.5,y=42" Note that  formatterL accepts arbitrary order of the parameters, or additional unused parameters.8formatter "unused parameter" initialBuffer y x :: String "x=0.5,y=42"$ Safe&'*;=>?uµ%&%& Safe &'*;=>?QVvK()()Mutable variablesSafe&'*;=>?w$%&()$  GeneratorsSafe &'*;=>?ST‚ + control-dslThis Yield0 keyword produces an element in a list generatorExamplesrandomGeneratorw is an example to create an xorshift pseudo-random number generator that returns an infinite list of generated numbers.:set -XTypeApplications:set -XRebindableSyntax1import Prelude hiding ((>>), (>>=), return, fail)import Control.Dslimport Data.Wordimport Data.Bits:{%randomGenerator :: Word32 -> [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:}#take 5 $ randomGenerator 24635342427[723471715,2497366906,2064144800,2008045182,3532304609]+,+,Safe*;<=>?ƒ   4  !"#$%&'()*+,-./01234   5   6   7 89:;<=>9?@A*control-dsl-0.2.0.2-9VlC7y9Gq9w2gZ1BNfQCcBControl.Dsl.PolyContControl.Dsl.MonadicControl.Dsl.EmptyControl.Dsl.ReturnControl.Dsl.Cont Control.DslControl.Dsl.ShiftControl.Dsl.StateControl.Dsl.State.PutControl.Dsl.State.GetControl.Dsl.YieldControl.AlternativeemptyPreludereturnfailControl.Dsl.DslShiftYieldGetPutMonadicReturnEmptyControl.Dsl.State.State Data.SequenceSeqContPolyCont runPolyCont$fPolyContMonadicma$fPolyContEmptymVoid$fPolyContReturnmVoid$fPolyContReturnrVoidrunCont!!whenunlessguard$fPolyContEmptyContVoid$fPolyContReturnContVoid$fPolyContkContaDsl>>==<<>=><=<>>forever ifThenElse$fPolyContShiftraState$fPolyContPut(->)()$fPolyContGet(->)s$fPolyContYieldCont()$fPolyContYield[]()baseGHC.IO.ExceptionIOError $fDslContra$fDslkracpsApplyGHC.BaseString