diff options
Diffstat (limited to 'std/prelude/results.pk')
-rw-r--r-- | std/prelude/results.pk | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/std/prelude/results.pk b/std/prelude/results.pk new file mode 100644 index 0000000..1209b40 --- /dev/null +++ b/std/prelude/results.pk @@ -0,0 +1,136 @@ +## std.results: Result types. +## This module is imported by default. + +use std[options, format] + +## The Result type. Represents either success or failure. +pub type Result[T, E] = union + Okay(T) + Error(E) + +## The Err interface. Useful for dynamically dispatching errors. +pub type Err = interface + str(Self): str + dbg(Self): str + +## A `Result` type that uses dynamically dispatched errors. +## The `Error` may be any type implementing `Err`. +pub type Result[T] = Result[T, ref Err] +## A `Result` type that only checks for success. +## Does not contain a value. +pub type Success[E] = Result[Unit, E] + +## Checks if a `Result` type was successful. +pub func is_ok[T, E](self: Result[T, E]): bool = + self of Okay(_) +## Checks if a `Result` type was not successful. +pub func is_err[T, E](self: Result[T, E]): bool = + self of Error(_) + +## Converts from a `Result[T, E]` to an `Option[T]`. +pub func ok[T, E](self: Result[T, E]): Option[T] = + if self of Okay(x): + Some(x) + else: + None() +## Converts from a `Result[T, E]` to an `Option[E]`. +pub func err[T, E](self: Result[T, E]): Option[E] = + if self of Error(x): + Some(x) + else: + None() + +## Applies a function to `T`, if self is `Okay`. +pub func map[T, E, U](self: Result[T, E], fn: T -> U): Result[U, E] = + match self + of Okay(x): + Okay(fn(x)) + of Error(e): + Error(e) +## Applies a function to `E`, if self is `Error`. +pub func map_err[T, E, F](self: Result[T, E], fn: E -> F): Result[T, F] = + match self + of Error(e): + Error(fn(e)) + of Okay(x): + Okay(x) + +## Applies a function to `T`, if it exists. Equivalent to `self.map(fn).flatten`. +pub func flatmap[T, E, U](self: Result[T, E], fn: T -> Result[U, E]): Result[U, E] = + match self + of Okay(x): + fn(x) + of Error(e): + Error(e) +## Converts from a `Result[Result[T, E], E]` to a `Result[T, E]`. +pub func flatten[T, E](self: Result[Result[T, E], E]): Result[T, E] = + match self + of Okay(Okay(x)): + Okay(x) + of Okay(Error(e)), Error(e): + Error(e) + +## Transposes a `Result[Option[T], E]` to an `Option[Result[T, E]]`. +pub func transpose[T, E](self: Result[Option[T], E]): Option[Result[T, E]] = + match self + of Okay(Some(x)): + Some(Okay(x)) + of Okay(None()), Error(_): + None() +## Transposes an `Option[Result[T, E]]` to a `Result[Option[T], E]`. Takes a default error. +pub func transpose[T, E](self: Option[Result[T, E]], error: E): Result[Option[T], E] = + match self + of Some(Okay(x)): + Okay(Some(x)) + of Some(Error(e)): + Error(e) + of None(): + Error(error) + +## Returns the inner value or a default. +pub func get_or[T, E](self: Result[T, E], default: T): T = + if self of Okay(x): x + else: default + +## Directly accesses the inner value. Throws an exception if `Error`. +pub func ![T, E](self: Result[T, E]): T = + match self + of Okay(x): x + of Error(e): raise e +## Directly accesses the inner error. Throws an exception of type T if `Okay`. +pub func get_err[T, E](self: Result[T, E]): E = + match self + of Error(e): e + of Okay(x): raise x + +## Indirect access. Propagates `Error`. +pub macro ?[T, E](self: Result[T, E]) = + quote: + match `self` + of Okay(x): x + of Error(e): return Error(e) + +## Overloads the `==` operation for use on Results. +pub func ==[T, E, F](a: Result[T, E], b: Result[T, F]): bool = + match (a, b) + of (Okay(x), Okay(y)): + x == y + of _: + false + +## Overloads the `str()` function for use on Results. +pub func str[T, E](self: Result[T, E]): str = + match self + of Some(x): + fmt("Okay({})", x.str) + of Error(e): + fmt("Error({})", e.str) + +examples: + let x: Error("fuck") = Okay(42) + func idk: Result[int, string] + +# references: +# https://doc.rust-lang.org/std/result/enum.Result.html +# https://github.com/arnetheduck/nim-results +# https://github.com/codex-storage/questionable |