aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/control/monad.lux
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/lux/control/monad.lux142
1 files changed, 142 insertions, 0 deletions
diff --git a/stdlib/source/lux/control/monad.lux b/stdlib/source/lux/control/monad.lux
new file mode 100644
index 000000000..71a873704
--- /dev/null
+++ b/stdlib/source/lux/control/monad.lux
@@ -0,0 +1,142 @@
+## Copyright (c) Eduardo Julian. All rights reserved.
+## This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+## If a copy of the MPL was not distributed with this file,
+## You can obtain one at http://mozilla.org/MPL/2.0/.
+
+(;module:
+ lux
+ (.. (functor #as F)
+ (applicative #as A)))
+
+## [Utils]
+(def: (fold f init xs)
+ (All [a b]
+ (-> (-> b a a) a (List b) a))
+ (case xs
+ #;Nil
+ init
+
+ (#;Cons x xs')
+ (fold f (f x init) xs')))
+
+(def: (map f xs)
+ (All [a b]
+ (-> (-> a b) (List a) (List b)))
+ (case xs
+ #;Nil
+ #;Nil
+
+ (#;Cons x xs')
+ (#;Cons (f x) (map f xs'))))
+
+(def: (reverse xs)
+ (All [a]
+ (-> (List a) (List a)))
+ (fold (lambda [head tail] (#;Cons head tail))
+ #;Nil
+ xs))
+
+(def: (as-pairs xs)
+ (All [a] (-> (List a) (List [a a])))
+ (case xs
+ (#;Cons x1 (#;Cons x2 xs'))
+ (#;Cons [x1 x2] (as-pairs xs'))
+
+ _
+ #;Nil))
+
+## [Signatures]
+(sig: #export (Monad m)
+ (: (A;Applicative m)
+ applicative)
+ (: (All [a]
+ (-> (m (m a)) (m a)))
+ join))
+
+## [Syntax]
+(macro: #export (do tokens state)
+ {#;doc (doc "Macro for easy concatenation of monadic operations."
+ (do Monad<Maybe>
+ [y (f1 x)
+ z (f2 z)]
+ (wrap (f3 z))))}
+ (case tokens
+ (#;Cons monad (#;Cons [_ (#;TupleS bindings)] (#;Cons body #;Nil)))
+ (let [g!@ (: AST [["" -1 -1] (#;SymbolS ["" "@"])])
+ g!map (: AST [["" -1 -1] (#;SymbolS ["" " map "])])
+ g!join (: AST [["" -1 -1] (#;SymbolS ["" " join "])])
+ g!apply (: AST [["" -1 -1] (#;SymbolS ["" " apply "])])
+ body' (fold (: (-> [AST AST] AST AST)
+ (lambda [binding body']
+ (let [[var value] binding]
+ (case var
+ [_ (#;TagS ["" "let"])]
+ (` (let (~ value) (~ body')))
+
+ _
+ (` (|> (~ value) ((~ g!map) (lambda [(~ var)] (~ body'))) (~ g!join)))
+ ))))
+ body
+ (reverse (as-pairs bindings)))]
+ (#;Right [state (#;Cons (` (;_lux_case (~ monad)
+ (~ g!@)
+ (;_lux_case (~ g!@)
+ {#applicative {#A;functor {#F;map (~ g!map)}
+ #A;wrap (~' wrap)
+ #A;apply (~ g!apply)}
+ #join (~ g!join)}
+ (~ body'))))
+ #;Nil)]))
+
+ _
+ (#;Left "Wrong syntax for do")))
+
+## [Functions]
+(def: #export (seqM monad xs)
+ (All [M a]
+ (-> (Monad M) (List (M a)) (M (List a))))
+ (case xs
+ #;Nil
+ (:: monad wrap #;Nil)
+
+ (#;Cons x xs')
+ (do monad
+ [_x x
+ _xs (seqM monad xs')]
+ (wrap (#;Cons _x _xs)))
+ ))
+
+(def: #export (mapM monad f xs)
+ (All [M a b]
+ (-> (Monad M) (-> a (M b)) (List a) (M (List b))))
+ (case xs
+ #;Nil
+ (:: monad wrap #;Nil)
+
+ (#;Cons x xs')
+ (do monad
+ [_x (f x)
+ _xs (mapM monad f xs')]
+ (wrap (#;Cons _x _xs)))
+ ))
+
+(def: #export (foldM monad f init xs)
+ (All [M a b]
+ (-> (Monad M) (-> b a (M a)) a (List b)
+ (M a)))
+ (case xs
+ #;Nil
+ (:: monad wrap init)
+
+ (#;Cons x xs')
+ (do monad
+ [init' (f x init)]
+ (foldM monad f init' xs'))))
+
+(def: #export (liftM Monad<M> f)
+ (All [M a b]
+ (-> (Monad M) (-> a b) (-> (M a) (M b))))
+ (lambda [ma]
+ (do Monad<M>
+ [a ma]
+ (wrap (f a)))))