CPS IO -> Async Interaction Tree Effect Runtime

I'm deeply satisfied to be building an interaction tree runtime where
the interaction trees are themselves computed via and represented by
trees. It's trees all the way down.
This commit is contained in:
2026-05-13 11:02:37 -05:00
parent 983a0cc5a7
commit 8f7684a1bb
6 changed files with 1965 additions and 117 deletions

86
demos/monadicIO.tri Normal file
View File

@@ -0,0 +1,86 @@
!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