I don’t understand the use-case for this change. I make extensive use of Failure tuples like this in combination with to_result
.
Quick review of tuple syntax:
Failure[:something, :something_else]
is exactly equivalent to
Failure([:something, :something_else])
therefore, when I need to convert None
to a Failure
tuple, I write
to_result([:something, :something_else])
The problem I see with this proposal is: if you are allowing a Result
type as an argument, what happens when you write
to_result(Success[:something, :something_else])
this should be a type error IMO, because to_result
is specifically meant for translating None to Failure and no other type.
I do see a possible use-case for block syntax, you might want to defer execution of that in a situation where producing the Failure is expensive, but I have not actually encountered this problem myself.
However, I would expect that the output of the block would become the inner value of the Failure, rather than accepting a Result type.
Finally, I would also like to demonstrate a monad helper that I use extensively called either
. It’s an alternative to yield
within an Operation
object that simplifies converting error results for common things.
# Utility helper to avoid .to_monad.or {} chaining
#
# @param [#to_monad] result, Dry::Monads::Result or object that responds to `to_monad`
# @param [Dry::Monads::Result::Failure, #to_proc, { :error => Symbol }] error
#
# @example With Yield
# user = yield fetch_user.(id).or { |err| Failure[:not_found, err] }
#
# @example With Either
# user = either fetch_user.(id), Failure(:not_found)
# user = either fetch_user.(id), ->(err) { Failure[:not_found, err] }
# user = either fetch_user.(ud), error: :not_found
#
# @raise [Dry::Monads::Do::Halt]
#
# @return the unwrapped successful value
def either(result, error)
failure =
case error
in { error: error_name }
proc { |err| Failure[error_name, err] }
in T::Procable
error
else
proc { error }
end
Dry::Monads::Do.bind result.to_monad.or(&failure)
end
So with that helper I could also write this transformation as
either None(), Failure[:something, :something_else]