blob: 2d96364ad6709c1a3cd38c74524f85589b69635e (
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
62
63
|
(.module:
[lux #*
[data
[collection
["." list ("list/." Fold<List>)]]]]
[//
["F" functor]])
## [Signatures]
(signature: #export (CoMonad w)
{#.doc (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 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 (#.Identifier ["" " _ "])])
g!map (: Code [_cursor (#.Identifier ["" " map "])])
g!split (: Code [_cursor (#.Identifier ["" " 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 (` ({(~' @)
({{#functor {#F.map (~ g!map)} #unwrap (~' unwrap) #split (~ g!split)}
(~ body')}
(~' @))}
(~ comonad)))
#.Nil)]))
(#.Left "'be' bindings must have an even number of parts."))
_
(#.Left "Wrong syntax for 'be'")))
|