!import "../lib/prelude.tri" !Local !import "../lib/io.tri" !Local -- Interaction Tree Effect Runtime -- -- The IO system is an interaction-tree effect runtime interpreted by a -- small-step machine with a cooperative scheduler. Primitive actions -- (putStr, readFile, writeFile, ...) are tagged nodes in an interaction -- tree. Sequencing is performed by the single generic `bind` constructor. -- -- pure x -- lift a pure value into IO -- bind action k -- run action, then apply k to its result -- thenIO a b -- run a, discard its result, then run b -- mapIO action f -- run action, then apply f to its result inside pure -- -- The runtime supports several effects beyond basic IO: -- ask -- read the current environment -- local f action -- run action with environment transformed by f -- get -- read the current mutable state -- put s -- replace the mutable state -- fork action -- spawn a concurrent task, returning a handle -- await handle -- wait for a forked task to complete -- yield -- yield control to the scheduler -- sleep ms -- suspend current task for N milliseconds -- -- File operations return a Result tree (see lib/base.tri): -- ok value -- pair true (pair value t) -- err msg -- pair false (pair msg t) -- -- Use onReadFile / onWriteFile for convenient branching. -- -- See demos/interactionTrees/ for smaller focused examples. -- Cooperative async demo. -- fork runs an action in the background. -- sleep suspends the current task for N milliseconds. -- await waits for a forked task and returns its value. -- -- Here the child sleeps for 2 s while the parent prints immediately. -- The parent's message appears first, proving interleaving. asyncDemo = ( bind (fork (bind (sleep 2000) (_ : bind (putStrLn "2000ms done sleeping!") (_ : pure "child2000 done")))) (handle2000 : bind (fork (bind (sleep 5000) (_ : bind (putStrLn "5000ms done sleeping!") (_ : pure "child5000 done")))) (handle5000 : bind (putStrLn "Parent first!") (_ : bind (await handle5000) (_ : await handle2000))))) main = io asyncDemo