Simple implementation of common ADTs (Maybe
, Result
) and their instances
of Functor
and Monad
typeclasses in Elixir.
This package is based on towel package but modifies and extends it in a few ways:
- add
Hayase.Maybe.unwrap/2
to provide fallback value (just likeAlgae.Maybe.from_maybe/2
fromalgae
package) unwrap
functions from bothMaybe
andResult
ADTs don't unwrap passed values recursively but do it one level deep only- return value of
Hayase.Functor.fmap/2
is always constructed with the same type constructor as input value - implement an instance of
Functor
typeclass for Elixir maps
hayase
package is not meant to replace other packages providing algebraic
and categorical abstractions - it aims to implement a small subset of their
functionality which seems to be enough for my needs.
Using Hayase.Types.Maybe
- before processing it's useful to wrap input value
with Hayase.Types.Maybe.wrap/1
to build Maybe
value automatically:
use Hayase
# -----------------------------------------------
# using with `Hayase.Typeclasses.Functor.fmap/2`
# -----------------------------------------------
"foo"
|> Maybe.wrap()
|> fmap(fn x -> x <> " bar" end)
|> fmap(fn x -> x <> " baz" end)
# => {:just, "foo bar baz"}
nil
|> Maybe.wrap()
|> fmap(fn x -> x <> " bar" end)
|> fmap(fn x -> x <> " baz" end)
# => :nothing
# -----------------------------------------------
# using with `Hayase.Typeclasses.Monad.bind/2`
# -----------------------------------------------
"foo"
|> Maybe.wrap()
|> bind(fn x -> Maybe.just(x <> " bar") end)
|> bind(fn x -> Maybe.just(x <> " baz") end)
# => {:just, "foo bar baz"}
"foo"
|> Maybe.wrap()
|> bind(fn x -> Maybe.just(x <> " bar") end)
|> bind(fn x -> Maybe.nothing(x <> " baz") end)
# => :nothing
nil
|> Maybe.wrap()
|> bind(fn x -> Maybe.just(x <> " bar") end)
|> bind(fn x -> Maybe.just(x <> " baz") end)
# => :nothing
# -----------------------------------------------
# unwrapping
# -----------------------------------------------
{:just, "foo bar baz"}
|> Maybe.unwrap()
# => "foo bar baz"
:nothing
|> Maybe.unwrap()
# => nil
:nothing
|> Maybe.unwrap("fallback value")
# => "fallback value"
Using Hayase.Types.Result
- as a rule it's not necessary to wrap input value
with Hayase.Types.Result.wrap/1
since in most cases it's already provided as
a Result
value (so called tagged tuple):
use Hayase
# -----------------------------------------------
# using with `Hayase.Typeclasses.Functor.fmap/2`
# -----------------------------------------------
{:ok, "foo"}
|> fmap(fn x -> x <> " bar" end)
|> fmap(fn x -> x <> " baz" end)
# => {:ok, "foo bar baz"}
{:error, "error"}
|> fmap(fn x -> x <> " bar" end)
|> fmap(fn x -> x <> " baz" end)
# => {:error, "error"}
# -----------------------------------------------
# using with `Hayase.Typeclasses.Monad.bind/2`
# -----------------------------------------------
{:ok, "foo"}
|> bind(fn x -> Result.ok(x <> " bar") end)
|> bind(fn x -> Result.ok(x <> " baz") end)
# => {:ok, "foo bar baz"}
{:ok, "foo"}
|> bind(fn x -> Result.error(x <> "error") end)
|> bind(fn x -> Result.ok(x <> " baz") end)
# => {:error, "error"}
# -----------------------------------------------
# unwrapping
# -----------------------------------------------
{:ok, "foo bar baz"}
|> Result.unwrap()
# => "foo bar baz"
{:error, "error"}
|> Result.unwrap()
# => "error"
If available in Hex, the package can be installed
by adding hayase
to your list of dependencies in mix.exs
:
def deps do
[
{:hayase, "~> 0.1"}
]
end
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/hayase.
- tests
- typespecs
- docs