Skip to content

Commit

Permalink
example: free monad
Browse files Browse the repository at this point in the history
  • Loading branch information
LighghtEeloo committed Oct 15, 2024
1 parent 006e286 commit cae4381
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lang/lib/exec/alg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ srcs = [
deps = []
bins = [
# "alg.zy",
"algtrans.zy",
# "algtrans.zy",
# "motrans.zy",
"free.zy",
]

std = "NoStd"
90 changes: 90 additions & 0 deletions lang/lib/exec/free.zy
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
codata Kont (R: CType) (A: VType) where
| .run : U (A -> R) -> R
end

def ! kont (R: CType) : Monad (Kont R) =
comatch
| .return A a -> fn .run k ->
! k a
| .bind A A' m f -> fn .run k ->
do~ ! m .run; fn a ->
! f a .run k
end
end

data Err where
| +Msg : String
end

data Empty where end

codata Handlers (R: CType) (K: CType) where
| .eff :
U (String -> U (Bool -> R) -> R) // print : String ~> Bool
-> U (Err -> U(Empty -> R) -> R) // fail : Err ~> Empty
-> U (Unit -> U(Bool -> R) -> R) // flip : Unit ~> Bool
-> K
end

codata Free (H: CType -> CType -> CType) (A: VType) where
| .run : forall (R: CType) . H R (U (A -> R) -> R)
end

def ! free : Monad (Free Handlers) =
comatch
| .return A a ->
fn .run R -> fn .eff print fail flip k -> ! k a
| .bind A A' m f -> fn .run R -> fn .eff print fail flip k' ->
! m .run (R) .eff print fail flip { fn a ->
! f a .run (R) .eff print fail flip k'
}
end
end

def ! print (s: String) : Free Handlers Bool =
fn .run R -> fn .eff print fail flip -> ! print s
end

def ! fail (e: Err) : Free Handlers Empty =
fn .run R -> fn .eff print fail flip -> ! fail e
end

def ! flip : Free Handlers Bool =
fn .run R -> fn .eff print fail flip -> ! flip ()
end

def ! print-os (s: String) (k: U (Bool -> OS)) : OS =
do~ ! write_line s;
! k +True()
end

def ! print-str (s: String) (k: U (Bool -> Ret String)) : Ret String =
do s' <- ! k +True();
! str_append s s'
end

def ! fail-os (e: Err) (_: U (Empty -> OS)) : OS =
match e
| +Msg(s) -> ! panic s
end
end

def ! flip-os (_: Unit) (kb: U (Bool -> OS)) : OS =
do~ ! random_int; fn i ->
do b <- ! mod i 2;
! if~ (OS) { ! int_eq b 0 } { ! kb +True() } { ! kb +False() }
end

main
let m = {
do~ ! free .bind (Bool) (Unit) { ! print "a" }; fn _ ->
do~ ! free .bind (Bool) (Unit) { ! print "b" }; fn _ ->
do~ ! free .bind (Bool) (Unit) { ! flip }; fn b ->
do~ ! free .bind (Bool) (Unit) {
! if (Free Handlers Bool) b { ! print "+" } { ! print "-" }
}; fn _ ->
! free .return (Unit) ()
} in
do~ ! m .run (OS) .eff print-os fail-os flip-os; fn _ ->
! exit 0
end
1 change: 1 addition & 0 deletions lang/lib/exec/proj.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ bins = [
"explosion.zy",
"fn-opt.zy",
"forall.zy",
"free.zy",
"hash.zy",
"ifz.zy",
"interpreter.zydeco",
Expand Down

0 comments on commit cae4381

Please sign in to comment.