aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/control/try.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/library/lux/control/try.lux')
-rw-r--r--stdlib/source/library/lux/control/try.lux153
1 files changed, 153 insertions, 0 deletions
diff --git a/stdlib/source/library/lux/control/try.lux b/stdlib/source/library/lux/control/try.lux
new file mode 100644
index 000000000..013553b04
--- /dev/null
+++ b/stdlib/source/library/lux/control/try.lux
@@ -0,0 +1,153 @@
+(.module:
+ [library
+ [lux #*
+ [abstract
+ [apply (#+ Apply)]
+ [equivalence (#+ Equivalence)]
+ ["." functor (#+ Functor)]
+ ["." monad (#+ Monad do)]]
+ [meta
+ ["." location]]]])
+
+(type: #export (Try a)
+ (#Failure Text)
+ (#Success a))
+
+(implementation: #export functor
+ (Functor Try)
+
+ (def: (map f ma)
+ (case ma
+ (#Failure msg)
+ (#Failure msg)
+
+ (#Success datum)
+ (#Success (f datum)))))
+
+(implementation: #export apply
+ (Apply Try)
+
+ (def: &functor ..functor)
+
+ (def: (apply ff fa)
+ (case ff
+ (#Success f)
+ (case fa
+ (#Success a)
+ (#Success (f a))
+
+ (#Failure msg)
+ (#Failure msg))
+
+ (#Failure msg)
+ (#Failure msg))
+ ))
+
+(implementation: #export monad
+ (Monad Try)
+
+ (def: &functor ..functor)
+
+ (def: (wrap a)
+ (#Success a))
+
+ (def: (join mma)
+ (case mma
+ (#Failure msg)
+ (#Failure msg)
+
+ (#Success ma)
+ ma)))
+
+(implementation: #export (with monad)
+ ## TODO: Replace (All [a] (M (Try a))) with (functor.Then M Try)
+ (All [M] (-> (Monad M) (Monad (All [a] (M (Try a))))))
+
+ (def: &functor (functor.compose (get@ #monad.&functor monad) ..functor))
+
+ (def: wrap (|>> (\ ..monad wrap) (\ monad wrap)))
+
+ (def: (join MeMea)
+ (do monad
+ [eMea MeMea]
+ (case eMea
+ (#Failure try)
+ (wrap (#Failure try))
+
+ (#Success Mea)
+ Mea))))
+
+(def: #export (lift monad)
+ (All [M a] (-> (Monad M) (-> (M a) (M (Try a)))))
+ (\ monad map (\ ..monad wrap)))
+
+(implementation: #export (equivalence (^open "_\."))
+ (All [a] (-> (Equivalence a) (Equivalence (Try a))))
+
+ (def: (= reference sample)
+ (case [reference sample]
+ [(#Success reference) (#Success sample)]
+ (_\= reference sample)
+
+ [(#Failure reference) (#Failure sample)]
+ ("lux text =" reference sample)
+
+ _
+ false
+ )))
+
+(def: #export (succeed value)
+ (All [a] (-> a (Try a)))
+ (#Success value))
+
+(def: #export (fail message)
+ (-> Text Try)
+ (#Failure message))
+
+(def: #export (assume try)
+ (All [a] (-> (Try a) a))
+ (case try
+ (#Success value)
+ value
+
+ (#Failure message)
+ (error! message)))
+
+(def: #export (to_maybe try)
+ (All [a] (-> (Try a) (Maybe a)))
+ (case try
+ (#Success value)
+ (#.Some value)
+
+ (#Failure message)
+ #.None))
+
+(def: #export (from_maybe maybe)
+ (All [a] (-> (Maybe a) (Try a)))
+ (case maybe
+ (#.Some value)
+ (#Success value)
+
+ #.None
+ (#Failure (`` (("lux in-module" (~~ (static .prelude_module)) .name\encode)
+ (name_of ..from_maybe))))))
+
+(macro: #export (default tokens compiler)
+ {#.doc (doc "Allows you to provide a default value that will be used"
+ "if a (Try x) value turns out to be #Failure."
+ "Note: the expression for the default value will not be computed if the base computation succeeds."
+ (= "bar"
+ (default "foo" (#..Success "bar")))
+ (= "foo"
+ (default "foo" (#..Failure "KABOOM!"))))}
+ (case tokens
+ (^ (list else try))
+ (#Success [compiler (list (` (case (~ try)
+ (#..Success (~' g!temp))
+ (~' g!temp)
+
+ (#..Failure (~ [location.dummy (#.Identifier ["" ""])]))
+ (~ else))))])
+
+ _
+ (#Failure "Wrong syntax for default")))