Packages

Result monad for Elixir inspired by Rust Result type.

Current section

Files

Jump to
rustic_result lib rustic_result.ex
Raw

lib/rustic_result.ex

defmodule Rustic.Result do
@moduledoc """
Documentation for `RusticResult`.
"""
defmodule UnhandledError do
@moduledoc "Error raised when trying to unwrap an Err result"
defexception [:reason]
@doc "Convert error to string"
@spec message(%__MODULE__{}) :: String.t()
def message(e) do
"Expected an Ok result, \"#{inspect(e.reason)}\" given."
end
end
defmodule MissingError do
@moduledoc "Error raised when trying to unwrap an Ok value"
defexception [:value]
@doc "Convert error to string"
@spec message(%__MODULE__{}) :: String.t()
def message(e) do
"Expected an Err result, \"#{inspect(e.value)}\" given."
end
end
@typedoc "Describe an Ok value"
@type ok :: {:ok, any()}
@typedoc "Describe an Err value"
@type err :: {:error, term()}
@typedoc "Describe a Result type"
@type t :: ok | err
@typedoc "A function that maps a value to a result"
@type f :: (any() -> t())
@doc "Wraps a value into an Ok result"
@spec ok(any()) :: ok()
def ok(v), do: {:ok, v}
@doc "Wraps a value into an Err result"
@spec err(term()) :: err()
def err(reason), do: {:error, reason}
@doc "Returns true if the Result is an Ok value"
@spec is_ok?(t()) :: boolean()
def is_ok?({:ok, _}), do: true
def is_ok?({:error, _}), do: false
@doc "Returns true if the Result is an Err value"
@spec is_err?(t()) :: boolean()
def is_err?({:ok, _}), do: false
def is_err?({:error, _}), do: true
@doc "Unwrap an Ok result, or raise an exception"
@spec unwrap!(t()) :: any()
def unwrap!({:ok, val}), do: val
def unwrap!({:error, reason}), do: raise UnhandledError, reason: reason
@doc "Unwrap an Err result, or raise an exception"
@spec unwrap_err!(t()) :: term()
def unwrap_err!({:ok, val}), do: raise MissingError, value: val
def unwrap_err!({:error, reason}), do: reason
@doc "Unwrap an Ok result, or return a default value"
@spec unwrap_or(t(), any()) :: any()
def unwrap_or({:ok, val}, _default), do: val
def unwrap_or({:error, _reason}, default), do: default
@doc """
Apply a function which returns a result to an Ok result, or propagates the
error.
"""
@spec and_then(t(), f()) :: t()
def and_then({:ok, val}, func), do: func.(val)
def and_then(err, _func), do: err
@doc """
Apply a function which returns a result to an Err result, or propagates the
Ok value.
"""
@spec or_else(t(), f()) :: t()
def or_else({:error, reason}, func), do: func.(reason)
def or_else(ok, _func), do: ok
end