Tracing failures
"Left" values of right-biased monads like Maybe
and Result
(as in, None()
and Failure()
) ignore blocks passed to fmap
and bind
. Because of this, these values travel across the application without any modification. If the place where a Failure
was constructed is burried somewhere deep in the app or library code it may be pretty hard to find out where exactly the error occurred.
This is a noticable downside compared to "good" old exceptions. To address it, every Failure(...)
and None()
value tracks the line where it was created:
# create_user.rb
require 'dry/monads'
class CreateUser
include Dry::Monads[:result]
def call
Failure(:no_luck)
end
end
require 'create_user'
create_user = CreateUser.new
create_user.() # => Failure(:no_luck)
create_user.().trace # => .../create_user.rb:8:in `call'
Note that the trace stores only one line of the stack so it shouldn't ever be a performance issue.