blob: 471c6bd2bafc51ef58e26bbbeb87f0c124dd9001 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
(.module:
lux
["F" //functor]
(lux/data/coll [list "list/" Fold<List>]))
## [Signatures]
(sig: #export (CoMonad w)
{#.doc "CoMonads are the opposite/complement to monads.
CoMonadic structures are often infinite in size and built upon lazily-evaluated functions."}
(: (F.Functor w)
functor)
(: (All [a]
(-> (w a) a))
unwrap)
(: (All [a]
(-> (w a) (w (w a))))
split))
## [Types]
(type: #export (CoFree F a)
{#.doc "The CoFree CoMonad."}
[a (F (CoFree F a))])
## [Syntax]
(def: _cursor Cursor ["" +0 +0])
(macro: #export (be tokens state)
{#.doc (doc "A co-monadic parallel to the \"do\" macro."
(let [square (function (_ n) (i/* n n))]
(be CoMonad<Stream>
[inputs (iterate i/inc 2)]
(square (head inputs)))))}
(case tokens
(#.Cons comonad (#.Cons [_ (#.Tuple bindings)] (#.Cons body #.Nil)))
(if (|> bindings list.size (n/% +2) (n/= +0))
(let [g!_ (: Code [_cursor (#.Symbol ["" " _ "])])
g!map (: Code [_cursor (#.Symbol ["" " map "])])
g!split (: Code [_cursor (#.Symbol ["" " split "])])
body' (list/fold (: (-> [Code Code] Code Code)
(function (_ binding body')
(let [[var value] binding]
(case var
[_ (#.Tag ["" "let"])]
(` (let (~ value) (~ body')))
_
(` (|> (~ value) (~ g!split) ((~ g!map) (function ((~ g!_) (~ var)) (~ body')))))
))))
body
(list.reverse (list.as-pairs bindings)))]
(#.Right [state (#.Cons (` ("lux case" (~ comonad)
{(~' @)
("lux case" (~' @)
{{#functor {#F.map (~ g!map)} #unwrap (~' unwrap) #split (~ g!split)}
(~ body')})}))
#.Nil)]))
(#.Left "'be' bindings must have an even number of parts."))
_
(#.Left "Wrong syntax for 'be'")))
|