sourcedemos/monads.xtl
1⍝!/usr/bin/env xetal
2⍝# The Maybe monad from the Maybe library: computations that can fail,
3⍝# chained so that the first failure stops the chain.
4⍝#
5⍝# Run it with ./demos/monads.xtl or "xetal run demos/monads.xtl", or as
6⍝# a notebook with "just show demos/monads.xtl". Each line prints a
7⍝# result, or the default (-1, or 0 for m_aybe) where a division by zero
8⍝# emptied the maybe. Read how b_ind chains steps right to left.
9
10ᵐ⁼u̲se< "Maybe"
11
12⍝## Division that can fail
13
14⍝# a u:d_iv b: a / b in a maybe, or the empty maybe when b is 0,
15⍝# instead of stopping the program.
16ᵘd̲iv ← { a b → b = 0 ? 'ᵐn̲othing◆ ᵐj̲ust a ÷ b }
17
18⍝ o_r takes a maybe's value, or a default (on the left) when it is
19⍝ empty.
20-1 ᵐo̲r 100 ᵘd̲iv 4
21-1 ᵐo̲r 100 ᵘd̲iv 0
22
23⍝## Chains
24
25⍝ b_ind chains steps that can fail, right to left like APL: 100 / 4,
26⍝ then / 5, then / 2.
27⍝# x halved, as a maybe.
28ᵘh̲alf ← { x → x ᵘd̲iv 2 }
29⍝# x divided by 5, as a maybe.
30ᵘf̲ifth ← { x → x ᵘd̲iv 5 }
31-1 ᵐo̲r 'ᵘh̲alf ᵐb̲ind 'ᵘf̲ifth ᵐb̲ind 100 ᵘd̲iv 4
32
33⍝ A zero anywhere in the chain gives the default: nothing after it
34⍝ runs.
35⍝# x divided by 0: always the empty maybe.
36ᵘb̲yZero ← { x → x ᵘd̲iv 0 }
37-1 ᵐo̲r 'ᵘh̲alf ᵐb̲ind 'ᵘb̲yZero ᵐb̲ind 100 ᵘd̲iv 4
38
39⍝## Mapping and both cases
40
41⍝ m_ap applies an ordinary function inside the maybe.
42-1 ᵐo̲r '{ ⍵ × 10 } ᵐm̲ap 9 ᵘd̲iv 3
43
44⍝ m_aybe takes both cases at once: a function and a default.
450 '{ ⍵ + 1 } ᵐm̲aybe 9 ᵘd̲iv 3
460 '{ ⍵ + 1 } ᵐm̲aybe 9 ᵘd̲iv 0