Last active
September 4, 2020 05:30
-
-
Save kana-sama/23516580ba59d8e83a898c1c28b8e55a to your computer and use it in GitHub Desktop.
Result/Either monad in Elixir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Result do | |
@type result :: any | |
@type reason :: any | |
@type ok :: {:ok, result} | |
@type error :: {:error, reason} | |
@type t :: ok | error | |
@spec ok(result) :: ok | |
def ok(result) do | |
{:ok, result} | |
end | |
@spec fail(reason) :: error | |
def fail(reason) do | |
{:error, reason} | |
end | |
@spec and_then(t, (result -> t)) :: t | |
def and_then({:error, _reason} = m, _callback), do: m | |
def and_then({:ok, result}, callback) do | |
callback.(result) | |
end | |
@spec and_then(t, (result -> result)) :: t | |
def map({:error, _reason} = m, _updater), do: m | |
def map({:ok, result}, updater) do | |
ok updater.(result) | |
end | |
@spec and_then(t, (reason -> reason)) :: t | |
def map_error({:ok, _result} = m, _updater), do: m | |
def map_error({:error, reason} = m, updater) do | |
fail updater.(reason) | |
end | |
end | |
defmodule TestModule do | |
def fetch do | |
Result.ok 9.0 | |
end | |
def div_ten_by_x(x) do | |
case x do | |
0.0 -> | |
Result.fail "zero" | |
_ -> | |
{:ok, 10 / x} # tuples are ok too | |
end | |
end | |
end | |
TestModule.fetch | |
|> IO.inspect # {:ok, 9.0} | |
|> Result.map(&(&1 + 1)) | |
|> IO.inspect # {:ok, 10.0} | |
|> Result.and_then(&TestModule.div_ten_by_x/1) | |
|> IO.inspect # {:ok, 1.0} | |
|> Result.map(&(&1 - 1)) | |
|> IO.inspect # {:ok, 0.0} | |
|> Result.and_then(&TestModule.div_ten_by_x/1) | |
|> IO.inspect # {:error, "zero"} | |
|> Result.map(&(&1 + 1)) | |
|> IO.inspect # {:error, "zero"} | |
|> Result.and_then(&TestModule.div_ten_by_x/1) | |
|> IO.inspect # {:error, "zero"} | |
|> Result.map_error(&String.capitalize/1) | |
|> IO.inspect # {:error, "Zero"} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment