(;module: lux ["F" //functor] (lux/data/coll [list "list/" Fold])) ## [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 [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!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 [(~ 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'")))