diff options
Diffstat (limited to 'stdlib/source/library/lux/control/try.lux')
-rw-r--r-- | stdlib/source/library/lux/control/try.lux | 153 |
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"))) |