ijaM      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL None7=KLThe  IOSpec f a is merely type synonym for IO an. Once you've tested a module, you can use these definitions to avoid having to change your type signatures.%Note that because this definition of  ignores its f argument, each of , &, etc., is simply an empty data type.None357KLThe (:<:) classThe coproduct of functors A value of type   f a is either a pure value of type a or some effect, determined by f . Crucially,   f is a monad, provided f is a functor.The fold over   values.M NOPQRST     M  NOPQRSTNone7;KLNThe X type class captures all the different types of operations that can be executed in the  monad.The U type contains all the primitive effects that are observable on the virtual machine.The  monad is essentially a state monad, modifying the store. Besides returning pure values, various primitive effects may occur, such as printing characters or failing with an error message.!The !0 function allocate a fresh location on the heap."The "g function removes the data stored at a given location. This corresponds, for instance, to emptying an MVar.#The #+ function returns a previously unallocated .$The $/ function kills the thread with the specified .UThe U> method is used to record when a thread cannot make progress.VWhen progress is made, the V6 function | ensures that any thread can be scheduled.%The %M function returns the data stored at a given heap location, if there is any.&The & constant is the  of the main process.'The ' and (. functions are the primitive counterparts of W and X in the  monad.)The )5 function overwrites a given location with new data.*The *7 function updates the process associated with a given .+The +3 scheduler provides a simple round-robin scheduler.,The , scheduler will never schedule forked threads, always scheduling the main thread. Only use this scheduler if your code is not concurrent.-The -w function is the heart of this library. Given the scheduling algorithm you want to use, it will run a value of type   f aN, returning the sequence of observable effects together with the final store..The . returns the final  after executing a computation.BewareW: this function assumes that your computation will succeed, without any other visible c. If your computation reads a character from the teletype, for instance, it will return an error./The /i function returns the effects a computation yields, but discards the final state of the virtual machine.JYZ[\]^_`abcdefghij klmnopq!"#$UV%&'()*r+,stuv-./wxyz{|}~  !"#$%&'()*+,-./  !"#$%&(')*+,-/.5YZ[\]^_`abcdefghij klmnopq!"#$UV%&'()*r+,stuv-./wxyz{|}~None47KL0An expression of type   0 a corresponds to an IOL computation that may print to or read from stdout and stdin respectively.There is a minor caveat here. I assume that stdin and stdout are not buffered. This is not the standard behaviour in many Haskell compilers.1The 1= function can be used to read a character from the teletype.2The 1< function can be used to print a character to the teletype. 012345012345012345012345None47;KLN 6A 6+ is a shared, mutable variable used by STM.8An expression of type IOSpec 8 a corresponds to an  computation that may use 9 and returns a value of type a. By itself, 88 is not terribly useful. You will probably want to use IOSpec (ForkS :+: STMS).9The 9! function atomically executes an 7 action.:The :/ function creates a new transactional variable.;The ;> function reads the value stored in a transactional variable.<The <C function overwrites the value stored in a transactional variable.=The =A function abandons a transaction and retries at some later time.>The >k function checks if its boolean argument holds. If the boolean is true, it returns (); otherwise it calls =.?The ? function takes two 7 actions stm1 and stm2 and performs stm1. If stm1 calls = it performs stm2. If stm1 succeeds, on the other hand, stm2 is not executed.6789:;<=>? 6789:;<=>? 8976:;<=?>6789:;<=>?None47KL@PA mutable variable storing a value of type a. Note that the types stored by an @ are assumed to be Typeable.AAn expression of type IOSpec IORefS a corresponds to an IOH computation that uses mutable references and returns a value of type a.BThe B) function creates a new mutable variable.CThe C7 function reads the value stored in a mutable variable.DThe D= function overwrites the value stored in a mutable variable.EThe E9 function applies a function to the value stored in and @.The  instance for the A monad. @ABCDE@ABCDEA@BCDE@ABCDENone+47KLFAn F is a shared, mutable variable.GAn expression of type IOSpec MVarS a corresponds to an IOO computation that uses shared, mutable variables and returns a value of type a. By itself, G8 is not terribly useful. You will probably want to use IOSpec (ForkS :+: MVarS).HThe H function creates a new F that is initially empty.IThe I* function removes the value stored in an F . If the F! is empty, the thread is blocked.JThe J function fills an F with a new value. If the F% is not empty, the thread is blocked. FGHIJFGHIJGFHIJFGHIJNone47;KLNKAn expression of type IOSpec ForkS a corresponds to an  computation that uses L and returns a value of type a. By itself, K8 is not terribly useful. You will probably want to use IOSpec (ForkS :+: MVarS) or IOSpec (ForkS :+: STMS).LThe L! function forks off a new thread.KLKLKLKL None7C  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL      !"#$%&'()*+,-./0123456 789:;<= >?@ABCDE FGHIJKLMNOPQRSTUVWXYZ7YZ8[\]"^_`abcdefgh#$ijklmnopqrstuvwxyz{|}~<vEJIOSpe_JhZxZXwFLKy3spTcP1GUooTest.IOSpec.SurrogateTest.IOSpec.TypesTest.IOSpec.VirtualMachineTest.IOSpec.TeletypeTest.IOSpec.STMTest.IOSpec.IORefTest.IOSpec.MVarTest.IOSpec.Fork Test.IOSpec:+:TeletypeSTMSIORefSMVarSForkSIOSpec:<:InlInrPureImpure foldIOSpecinjectStepBlock ExecutablestepEffectDoneReadCharPrintFailVMStore SchedulerThreadIdLocData initialStoreallocemptyLoc freshThreadId finishThread lookupHeapmainTidreadChar printChar updateHeap updateSoup roundRobinsingleThreaded runIOSpec execIOSpec evalIOSpecgetCharputCharputStrputStrLngetLineTVarSTM atomicallynewTVarreadTVar writeTVarretrycheckorElseIORefnewIORef readIORef writeIORef modifyIORefMVar newEmptyMVartakeMVarputMVarforkIOinj $f:<:f:+: $f:<:f:+:0$f:<:ff $fFunctor:+: $fMonadIOSpec$fApplicativeIOSpec$fFunctorIOSpec blockThreadresetBlockedThreadsbase System.IOProcessMainAuxfreshheapnextTidblockedThreadsfinishedThreads scheduler threadSoup ThreadSoup ThreadStatusRunningFinishedHeap modifyFresh modifyHeap modifyNextTidmodifyBlockedThreadsmodifyFinishedThreadsmodifySchedulermodifyThreadSoupupdate streamSchedexecVMgetNextThreadIdschedule internalError$fExecutable:+: $fEqEffect $fMonadEffect$fApplicativeEffect$fFunctorEffect$fShowScheduler$fArbitraryScheduler$fCoArbitraryThreadId$fArbitraryThreadIdGetCharPutChar$fExecutableTeletype$fFunctorTeletypeghc-prim GHC.TypesIO STMReturnNewTVarReadTVar WriteTVarRetryOrElse Atomically executeSTM $fMonadSTM$fApplicativeSTM $fFunctorSTM$fExecutableSTMS $fFunctorSTMS$fExecutableIORefSNewIORef ReadIORef WriteIORef$fFunctorIORefS NewEmptyMVarTakeMVarPutMVar$fExecutableMVarS$fFunctorMVarSFork$fExecutableForkS$fFunctorForkS