lambda-uc-0.1.0.0
Safe HaskellSafe
LanguageGHC2021

LambdaUC.Syntax.Async.Eval

Synopsis

Execution Syntax

This section defines syntax for distributed exection of processes.

You define your processes and their links as a value of type Exec, and then run it using runExec.

You start with the processes defined as AsyncT m ach i i a` wrapped in ExecProc, then you combine them using ExecFork, ExecLink and ExecSwap until you've linked all the free ports and left with Exec m '[] NextSend a. The latter can be evaluated with runExec to yield the final result of evaluation.

Only one process in the whole execution is allowed to return a result. It is the (only) process that finishes in NextSend state, all the other processes are forced to have their return type Void (and never finish). These conditions are checked statically by the typeclass restrictions of Exec constructors.

Function runExec returns the result of the process that termiates in NextSend.

data Exec ach (i :: InitStatus) where #

Constructors

ExecProc

An execution consisting of one process.

Fields

ExecSpawnOnDemand :: forall l r ports. ConstrAllD Ord l -> ConstrAllD Ord r -> KnownHPPortsD ports -> KnownLenD l -> KnownLenD r -> (HListPair l r -> Exec ports InitAbsent) -> Exec (MapConcat2 l r ports) InitAbsent 
ExecFork

Combine two executions.

Fields

ExecSwap

Swap positions of two adjacent free ports.

Fields

ExecLink

Link two adjacent free ports of a given execution (making them bound).

Fields

  • :: ListSplitD l p ((x :> y) : l')

    Proof of l == p ++ [x :> y] ++ l'

  • -> ListSplitD l' p' ((y :> x) : rest)

    Proof of l' == p' ++ [y :> x] ++ rest

  • -> Exec l st

    Exectuion where we want to link the ports

  • -> Exec (Concat p (Concat p' rest)) st
     

runExec :: Exec '[] (InitPresent a) -> PrAlgo a #

Run an execution.

Note that the list of free ports must be empty, i.e. all ports must be bound for an execution to be defined.

Monad for Building Executions

This section defines the ExecBuilder monad that simplifies the construction of Exec exections. Any Exec value is built like a tree where each node is marked with one of constructors of Exec: ExecFork has two children nodes, ExecProc is a leaf (no children nodes), while ExecSwap and ExecFork have one child each.

This structure, while precisely matching the technical aspect of constructing an execution, are not so convenient for human to build. Especially, if your Exec formala is complex and you want to build it gradually and see intermediate results.

The ExecBuilder monad aids in building Exec values in a modular way and providing the programmer with feedback at each step. Each ExecBuilder action internally stores a function Exec l m i res -> Exec l' m i' res' or a function () -> Exec l m i res (given by the ExecIndex). Two actions can be composed together if the corresponding functions compose.

To get a runnable execution Exec '[] m i res, define a value of type ExecBuilder m ExecIndexInit (ExecIndexSome l i res) () and pass it to runExecBuilder. The result can be passed to runExec to actually run it. The basic actions available in ExecBuilder are forkLeft, forkRight, link and swap.

newtype ExecBuilder i j a #

Constructors

ExecBuilder 

Fields

Instances

Instances details
XApplicative ExecBuilder # 
Instance details

Defined in LambdaUC.Syntax.Async.Eval

Methods

xpure :: forall a (p :: k). a -> ExecBuilder p p a #

(<*>:) :: forall (p :: k) (q :: k) a b (r :: k). ExecBuilder p q (a -> b) -> ExecBuilder q r a -> ExecBuilder p r b #

xliftA2 :: forall a b c (p :: k) (q :: k) (r :: k). (a -> b -> c) -> ExecBuilder p q a -> ExecBuilder q r b -> ExecBuilder p r c #

(*>:) :: forall (p :: k) (q :: k) a (r :: k) b. ExecBuilder p q a -> ExecBuilder q r b -> ExecBuilder p r b #

(<*:) :: forall (p :: k) (q :: k) a (r :: k) b. ExecBuilder p q a -> ExecBuilder q r b -> ExecBuilder p r a #

XMonad ExecBuilder # 
Instance details

Defined in LambdaUC.Syntax.Async.Eval

Methods

(>>=:) :: forall a b (p :: k) (q :: k) (r :: k). ExecBuilder p q a -> (a -> ExecBuilder q r b) -> ExecBuilder p r b #

(>>:) :: forall a b (p :: k) (q :: k) (r :: k). ExecBuilder p q a -> ExecBuilder q r b -> ExecBuilder p r b #

xreturn :: forall a (p :: k). a -> ExecBuilder p p a #

Functor (ExecBuilder i j) # 
Instance details

Defined in LambdaUC.Syntax.Async.Eval

Methods

fmap :: (a -> b) -> ExecBuilder i j a -> ExecBuilder i j b #

(<$) :: a -> ExecBuilder i j b -> ExecBuilder i j a #

data ExecIndex #

Index of the ExecBuilder monad.

Constructors

ExecIndexInit

We haven't started any executions

ExecIndexSome [Port] InitStatus

An execution with given ach, i, and res is started

Instances

Instances details
XApplicative ExecBuilder # 
Instance details

Defined in LambdaUC.Syntax.Async.Eval

Methods

xpure :: forall a (p :: k). a -> ExecBuilder p p a #

(<*>:) :: forall (p :: k) (q :: k) a b (r :: k). ExecBuilder p q (a -> b) -> ExecBuilder q r a -> ExecBuilder p r b #

xliftA2 :: forall a b c (p :: k) (q :: k) (r :: k). (a -> b -> c) -> ExecBuilder p q a -> ExecBuilder q r b -> ExecBuilder p r c #

(*>:) :: forall (p :: k) (q :: k) a (r :: k) b. ExecBuilder p q a -> ExecBuilder q r b -> ExecBuilder p r b #

(<*:) :: forall (p :: k) (q :: k) a (r :: k) b. ExecBuilder p q a -> ExecBuilder q r b -> ExecBuilder p r a #

XMonad ExecBuilder # 
Instance details

Defined in LambdaUC.Syntax.Async.Eval

Methods

(>>=:) :: forall a b (p :: k) (q :: k) (r :: k). ExecBuilder p q a -> (a -> ExecBuilder q r b) -> ExecBuilder p r b #

(>>:) :: forall a b (p :: k) (q :: k) (r :: k). ExecBuilder p q a -> ExecBuilder q r b -> ExecBuilder p r b #

xreturn :: forall a (p :: k). a -> ExecBuilder p p a #

runExecBuilder :: ExecBuilder ExecIndexInit (ExecIndexSome l st) () -> MatchExecIndex (ExecIndexSome l st) #

Extract the internal Exec from ExecBuilder.

Note that `ExecBuilder m i j ()` internally stores a function MatchExecIndex i -> MatchExecIndex j. The function can be extracted using runXWriter.

At the same time, MatchExecIndex ExecIndexInit = ()`. Therefore, ExecBuilder m ExecIndexInit (ExecIndexSome l i res) stores a function () -> Exec m l i res, which is isomorphic to just value Exec m l i res, which this functions extracts.

Actions

The following are basic actions you can perform in ExecBuilder. The process, forkLeft, forkRight, link, swap correpond to the constructors of Exec. The difference between forkLeft and forkRight is merely in the order of composing the child nodes.

The execGuard = xreturn () has no effect in the monad, but can be inserted in-between other operations in ExecBuilder to annotate the current context. This can be used to document the code, while having the compiler verify that the annotation is correct. In some rare cases, execGuard can also be used to resolve ambiguous types.

process #

Arguments

:: InitStatusIndexRet st i res 
=> AsyncT l i i res

The program that the created process will run

-> ExecBuilder ExecIndexInit (ExecIndexSome l st) () 

forkLeft #

Arguments

:: (InitStatusComp st st', KnownLen l) 
=> ExecBuilder ExecIndexInit (ExecIndexSome l' st') ()

Right branch of the fork

-> ExecBuilder (ExecIndexSome l st) (ExecIndexSome (Concat l l') (InitStatusOr st st')) () 

forkRight #

Arguments

:: (InitStatusComp st st', KnownLen l) 
=> ExecBuilder ExecIndexInit (ExecIndexSome l st) ()

Left branch of the fork

-> ExecBuilder (ExecIndexSome l' st') (ExecIndexSome (Concat l l') (InitStatusOr st st')) () 

link #

Arguments

:: ListSplitD l p ((x :> y) : l')

Proof of l == p ++ [(x, y)] ++ l'

-> ListSplitD l' p' ((y :> x) : rest)

Proof of l' == p' ++ [(y, x)] ++ rest

-> ExecBuilder (ExecIndexSome l st) (ExecIndexSome (Concat p (Concat p' rest)) st) () 

swap #

Arguments

:: ListSplitD l p (f : l')

Proof of l == p ++ (f:l')

-> ListSplitD l' p' (s : rest)

Proof of l' == p' ++ (s:rest)

-> ExecBuilder (ExecIndexSome l st) (ExecIndexSome (Concat p (s : Concat p' (f : rest))) st) () 

execGuard :: forall l st. ExecBuilder (ExecIndexSome l st) (ExecIndexSome l st) () #

Following are the versions of process, forkLeft and forkRight that take the proofs as explicit arguments instead of implicit typeclass constraints.

process' #

Arguments

:: InitStatusIndexRetD st i res

Proof of res not being Void only if i == NextSend

-> AsyncT l i i res

The program that the created process will run

-> ExecBuilder ExecIndexInit (ExecIndexSome l st) () 

forkLeft' #

Arguments

:: InitStatusCompD st st'

Proof of i and i' not being NextSend both

-> KnownLenD l

Length of list l (left branch)

-> ExecBuilder ExecIndexInit (ExecIndexSome l' st') ()

Right branch of the fork

-> ExecBuilder (ExecIndexSome l st) (ExecIndexSome (Concat l l') (InitStatusOr st st')) () 

forkRight' #

Arguments

:: InitStatusCompD st st'

Proof of i and i' not being NextSend both

-> KnownLenD l

Length of list l (left branch)

-> ExecBuilder ExecIndexInit (ExecIndexSome l st) ()

Left branch of the fork

-> ExecBuilder (ExecIndexSome l' st') (ExecIndexSome (Concat l l') (InitStatusOr st st')) () 

Helper functions