Show HN: Result monad for Elixir inspired by Rust Result type
hexdocs.pm
hexdocs.pm
with {:ok, fh} <- maybe_open_file("filename.foo"),
{:ok, line} <- maybe_read_line(fh),
:ok <- try_close_fh(fh) do
{:line_received, line}
end
This gets you the same kind of flow, and is much more idiomatic Elixir.That being said, I have wished this convention could be more formalized. If you want to use this code base across your platform, knock your socks off. Elixir I feel like hits a sweet spot between flexibility+power and readability. Strong community conventions seem to help a lot as well.
This package does look nice; I appreciate the README and the docs that they put together—nice to see some thought and care put into a little project like this. :)
some_operation()
|> and_then(&some_other_operation/1)
|> or_else(&some_error_handling/1)
|> and_then(&another_operation/1)
The first and second step can fail and be handled by the third step, then continuing normally with the fourth step.Doing this with a with statement is awkward (unless I've been doing it wrong).
Thanks for the feedback anyway :)
I've been burned by this in other projects (see e.g. https://github.com/0xYUANTI/tulib/blob/master/include/types....)
You code will soon be a mish-mash of thunk(lift(unlift(thunk(err))))s
These things have to be a part of the language, or not at all
err
|> thunk()
|> unlift()
|> lift()
|> thunk()
Which is already more readable. And I choosed the Rust terminology for a reason, I think and_then/or_else is way clearer than fmap/bind.But I agree, I would love for Elixir to have a builtin Result type.
Welcome to Elixir! My company uses Elixir extensively, but I'm trying to get us to use some Rust for some NIFs and some other projects that would benefit from some performance. Both languages are really great and I derive great joy from using them. :)
I was copy/pasting bits of this code in multiple projects, this quickly became annoying.
Why not make it a functor too and add map()?
ok(1) |> map(fn v -> v + 1 end)
# ok(2)
Of course you can also make it a bifunctor by implementing bimap().
And what about filter()?
Honestly it was made just to scratch an itch I had for a while.
It's a pretty awesome feature indeed.
Though to be fair the examples in this library aren't using the correct syntax to be tested.
Also that's what I love about Erlang/Elixir, you don't need to know the language to be able to read code written in it.
If you want to go pedatic we can start discussing the type theory papers they appear on.
I could implement map/fmap/bind/lift/unlift/return/...
But I choosed and_then/or_else/unwrap/...