Skip to content

Commit

Permalink
Some more work on monads
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinborner committed Jun 7, 2024
1 parent eb21453 commit dba4ea4
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 46 deletions.
6 changes: 6 additions & 0 deletions samples/fun/IO.bruijn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# read two lines using monadic I/O
# printf "i love\nmonads\n" | bruijn IO.bruijn

:import std/IO .

main read-line >>= [read-line >>= [return [0 2 1]]]
27 changes: 27 additions & 0 deletions samples/fun/rng-state.bruijn
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# MIT License, Copyright (c) 2024 Marvin Borner
# generates three pseudo-random integers using a state monad
# printf <seed:number> | bruijn rng-state.bruijn

:import std/Combinator .
:import std/String .
:import std/Number .
:import std/Monad/State .

max (+1000)

rand [[[0 1 1]] rng]
rng (+1103515245) ⋅ 0 + (+12345) % max

rand-bool map even? rand

# accumulating bind (reversed)
triple1 rand >>= (rand >>= (rand >>= [[[[[0 3 [0 3 [0 3 [[0]]]]]]]]]))

:test ((triple1 (+50) [[1]]) =? (+745)) ([[1]])

# normal bind
triple2 rand >>= [rand >>= [rand >>= [[[0 4 [0 4 [0 4 [[0]]]]]]]]]

:test ((triple2 (+50) [[1]]) =? (+595)) ([[1]])

main string→number → triple2
12 changes: 12 additions & 0 deletions std/IO.bruijn
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# MIT License, Copyright (c) 2024 Marvin Borner

:input std/Monad/List .

:import std/Char C
:import std/Combinator .

# reads a single char monadically
get-char read

# reads a line monadically
get-line y [read >>= [(C.eq? 0 '\n') (pure [[0]]) (1 >>= [pure [0 2 1]])]]
49 changes: 3 additions & 46 deletions std/Monad.bruijn
Original file line number Diff line number Diff line change
@@ -1,47 +1,4 @@
# MIT License, Copyright (c) 2023 Marvin Borner
# monadic interface for anything based on lists (e.g. IO, strings)
# afaik originally proposed by John Tromp and inspired by Haskell
# MIT License, Copyright (c) 2024 Marvin Borner
# just a reference to the list monad (default interface)

:import std/List .
:import std/Combinator .

read [0] ⧗ a → (M a)

return [[1 : 0]] ⧗ a → (M a)

pure return ⧗ a → (M a)

# monadic bind operator
…>>=… [[[2 0 1]]] ⧗ (M a) → (a → (M b)) → (M a)

:test ((read >>= return) "woa") ("woa")

# monadic reverse bind operator
…=<<… \…>>=… ⧗ (a → (M b)) → (M a) → (M b)

:test ((return =<< read) "woa") ("woa")

# monadic compose operator
…>>… [[1 >>= [1]]] ⧗ (M a) → (M b) → (M b)

:test ((read >> (return 'a')) "hah") ("aah")

# monadifies a list
lift-m map ⧗ (a → b) → (M a) → (M b)

# monadifies a list with two monadic arguments
lift-m2 [[[concat ([[4 1 0] <$> 1] <$> 1)]]] ⧗ (a → b → c) → (M a) → (M b) → (M c)

# evaluates monadic actions
sequence foldr (lift-m2 cons) {}empty ⧗ (List (M a)) → (M (List a))

>‣ [sequence ∘∘ 0]

# traverses list based on modifier
traverse sequence ∘∘ map ⧗ (a → (M b)) → (N a) → (M (N b))

# performs action n times
replicate-m >replicate ⧗ Number → (M a) → (M (List a))

# maps elements to a monadic action
map-m >map ⧗ (a → (M b)) → (List a) → (M (List b))
:input std/Monad/List
50 changes: 50 additions & 0 deletions std/Monad/List.bruijn
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# MIT License, Copyright (c) 2023 Marvin Borner
# monadic interface for anything based on lists (e.g. IO, strings)
# afaik originally proposed by John Tromp and inspired by Haskell

:import std/List .
:import std/Combinator .

read [0] ⧗ a → (M a)

return [[1 : 0]] ⧗ a → (M a)

pure return ⧗ a → (M a)

# monadic bind operator
bind [[[2 0 1]]] ⧗ (M a) → (a → (M b)) → (M a)

…>>=… bind

:test ((read >>= return) "woa") ("woa")

# monadic reverse bind operator
…=<<… \…>>=… ⧗ (a → (M b)) → (M a) → (M b)

:test ((return =<< read) "woa") ("woa")

# monadic compose operator
…>>… [[1 >>= [1]]] ⧗ (M a) → (M b) → (M b)

:test ((read >> (return 'a')) "hah") ("aah")

# monadifies a list
lift-m map ⧗ (a → b) → (M a) → (M b)

# monadifies a list with two monadic arguments
lift-m2 [[[concat ([[4 1 0] <$> 1] <$> 1)]]] ⧗ (a → b → c) → (M a) → (M b) → (M c)

# evaluates monadic actions
sequence foldr (lift-m2 cons) {}empty ⧗ (List (M a)) → (M (List a))

>‣ [sequence ∘∘ 0]

# traverses list based on modifier
traverse sequence ∘∘ map ⧗ (a → (M b)) → (N a) → (M (N b))

# performs action n times
replicate-m >replicate ⧗ Number → (M a) → (M (List a))

# maps elements to a monadic action
map-m >map ⧗ (a → (M b)) → (List a) → (M (List b))

12 changes: 12 additions & 0 deletions std/Monad/State.bruijn
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# MIT License, Copyright (c) 2024 Marvin Borner

:import std/Combinator .

# scala: s0 ⇒ { (s1, a) = run(s0); (s1, f(a)) }
map [[[1 0 [[[0 2 (5 1)]]]]]] ⧗ (a → b) → (State s a) → (State s b)

# monadic bind/flat-map operator
# scala: s0 ⇒ { (s1, a) = run(s0); f(a).run(s1) }
bind [[[2 0 [[3 0 1]]]]] ⧗ (State s a) → (a → (State s b)) → (State s b)

…>>=… bind

0 comments on commit dba4ea4

Please sign in to comment.