Add this line to your Gemfile
Every monad has corresponding value constructors. For example, the
Maybe monad has two of them:
None(). It also has the
Maybe(...) method. All three methods start with a capital letter similarly to built-in Ruby methods like
Kernel#Hash(...). Value constructors are not available globally, you need to add them with a mixin.
To add the
Maybe constructors add
Dry::Monads[:maybe] to your class:
require 'dry/monads' class CreateUser # this line loads the Maybe monad and adds # Some(...), None(), and Maybe(...) to CreateUser include Dry::Monads[:maybe] def call(params) # ... if valid?(params) None() else Some(create_user(params)) end end end
Example in the docs may use
extend Dry::Monads[...] for brevity but you normally want to use
include in production code.
require 'dry/monads' class CreateUser # Adds Maybe and Result. The order doesn't matter include Dry::Monads[:maybe, :result] end
require 'dry/monads' class ResultCalculator include Dry::Monads[:result, :do] def calculate(input) value = Integer(input) value = yield add_3(value) value = yield mult_2(value) Success(value) end def add_3(value) if value > 1 Success(value + 3) else Failure("value was less than 1") end end def mult_2(value) if value % 2 == 0 Success(value * 2) else Failure("value was not even") end end end c = ResultCalculator.new c.calculate(3) # => Success(12) c.calculate(0) # => Failure("value was less than 1") c.calculate(2) # => Failure("value was not even")
Some constructors have shortcuts for wrapping arrays:
require 'dry/monads' class CreateUser include Dry::Monads[:result] def call(params) # ... # Same as Failure([:user_exists, params: params]) Failure[:user_exists, params: params] end end
Some values can be converted to others or they can have methods that use other monads. By default, dry-monads doesn't load all monads so you may have troubles like this:
extend Dry::Monads[:result] Success(:foo).to_maybe # RuntimeError: Load Maybe first with require 'dry/monads/maybe'
To work around you may either load
maybe to the mixin:
extend Dry::Monads[:result, :maybe] Success(:foo).to_maybe # => Some(:foo)
For the same reason
Dry::Monads.Success(...), and some other constructors are not available until you explicitly load the monads with