!import "../lib/base.tri" !Local !import "../lib/list.tri" !Local !import "../lib/io.tri" !Local -- Monadic IO in tricu -- -- The IO system is a free monad interpreted by the host. Primitive actions -- (putStr, readFile, writeFile, ...) do not carry their own continuations. -- 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 -- -- File operations return a Result tree (see lib/base.tri): -- ok value -- pair true (pair value t) -- err code -- pair false (pair code t) -- -- Use onReadFile / onWriteFile for convenient branching. -- ---------------------------------------------------------------------------- -- Example 1: Greet and return a pure value. -- putStrLn writes to stdout; pure lifts "done" into IO. -- ---------------------------------------------------------------------------- greet = (name : bind (putStrLn (append "Hello, " name)) (_ : pure "done")) -- ---------------------------------------------------------------------------- -- Example 2: Read a file safely. -- readFile returns a Result. matchResult branches on ok / err. -- ---------------------------------------------------------------------------- safeRead = (path : bind (readFile path) (result : matchResult (err rest : pure "missing") (contents rest : pure contents) result)) -- ---------------------------------------------------------------------------- -- Example 3: Write, then read back. -- thenIO discards the writeFile Result and continues. -- ---------------------------------------------------------------------------- writeThenRead = (path text : thenIO (writeFile path text) (readFile path)) -- ---------------------------------------------------------------------------- -- Example 4: Transform an IO result. -- mapIO applies a pure function to the value produced by an action. -- ---------------------------------------------------------------------------- shout = (path : mapIO (safeRead path) (text : append text "!!!")) -- ---------------------------------------------------------------------------- -- Example 5: Cooperative async. -- 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 "Done sleeping!") (_ : pure "child done")))) (handle : bind (putStrLn "Parent first!") (_ : await handle))) -- ---------------------------------------------------------------------------- -- Main action - run the async demo. -- ---------------------------------------------------------------------------- main = io asyncDemo