Skip to content

Instantly share code, notes, and snippets.

@clinuxrulz
Created May 22, 2025 08:59
Show Gist options
  • Select an option

  • Save clinuxrulz/76ac4647cc84e4aad5c215183abd3218 to your computer and use it in GitHub Desktop.

Select an option

Save clinuxrulz/76ac4647cc84e4aad5c215183abd3218 to your computer and use it in GitHub Desktop.
Monadic handles for return values in do-notation for Cont
import { Cont } from "prelude";
let div = document.createElement("div");
div.style.setProperty("position", "absolute");
div.style.setProperty("left", "20px");
div.style.setProperty("top", "20px");
div.style.setProperty("width", "300px");
div.style.setProperty("z-index", "100");
div.style.setProperty("background-color", "rgba(0,0,0,0.7)");
setTimeout(() => {
document.body.appendChild(div);
main().run();
}, 3000);
export function onUnload() {
document.body.removeChild(div);
}
function main(): Cont<void> {
return do_(() => {
fork(proc("A", 4));
fork(proc("B", 2));
dequeue();
print("done main.");
let name = ask("Whats your name?");
exec(name.then(
(name) => do_(() =>
print(`Hello: ${name}`))
));
});
}
function proc(id: string, n: number): Cont<void> {
return do_(() => {
for (let i = 1; i <= n; ++i) {
sleep(1000);
print(`${id}: ${i}`);
pause();
}
});
}
let doContext: Cont<void> | undefined = undefined;
function do_(fn: () => void): Cont<void> {
let outer = doContext;
try {
doContext = undefined;
fn();
return doContext ?? Cont.of<void>((k) => k());
} finally {
doContext = outer;
}
}
function exec(instr: Cont<void>) {
if (doContext == undefined) {
doContext = instr;
} else {
doContext = doContext.then((_) => instr);
}
}
function ask(msg: string): Cont<string> {
let result: string | undefined = undefined;
let kResult: ((a: string) => void) | undefined = undefined;
exec(Cont.of((k) => {
result = window.prompt(msg);
if (kResult != undefined) {
kResult(result);
}
k();
}));
return Cont.of((k) => {
if (result != undefined) {
k(result);
} else {
kResult = k;
}
});
}
function print(msg: string) {
exec(Cont.of((k) => {
div.append(msg);
div.appendChild(document.createElement("br"));
k();
}));
}
function sleep(ms: number) {
exec(Cont.of((k) => {
setTimeout(k, ms);
}));
}
const processQueue: Cont<void>[] = [];
function pause() {
exec(Cont.callCC<void, void>((k) => {
processQueue.push(k());
return do_(dequeue);
}));
}
function dequeue() {
exec(Cont.of<void>((k) => {
if (processQueue.length != 0) {
let next = processQueue.shift();
next.run(k);
return;
}
k();
}));
};
function fork(proc: Cont<void>) {
exec(Cont.of((k) => {
processQueue.push(
proc.then((_) => do_(dequeue))
);
k();
}));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment