dry-types

v1.8 v1.7
  1. Introduction
  2. Getting Started
  3. Built-in Types
  4. Type Attributes
  5. Default Values
  6. Fallbacks
  7. Sum
  8. Constraints
  9. Hash Schemas
  10. Array With Member
  11. Enum
  12. Map
  13. Custom Types
  14. Custom Type Builders
  15. Extensions
    1. Maybe
    2. Monads

TOC

  1. dry-monads Do notation

Monads

The :monads extension provides a #to_monad method that returns a Result compatible with dry-monads.

The .try method returns a simple Result that's defined within dry-types (i.e. Dry::Types::Result).
If you want to use the result with dry-monads, you can load this extension and call #to_monad on the Dry::Types::Result to get a Result that's defined in dry-monads (i.e. Dry::Monads::Result). This will let you use the dry-monads methods on the result.

To enable the :monads extension:

require 'dry/types'
Dry::Types.load_extensions(:monads)
Types = Dry.Types()

After loading the extension, you can leverage the .to_monad method:

result = Types::String.try('Jane')
result.class            # => Dry::Types::Result::Success
monad = result.to_monad # => Success("Jane")
monad.class             # => Dry::Monads::Result::Success
monad.value!            # => 'Jane'

result = Types::String.try(nil)
result.class            # => Dry::Types::Result::Failure
monad = result.to_monad # => Failure([...])
monad.class             # => Dry::Monads::Result::Failure
monad.failure           # => [#<Dry::Types::ConstraintError: ...>, nil]
monad
  .fmap { |result| puts "passed: #{result.inspect}" }
  .or   { |error, input| puts "input '#{input.inspect}' failed with error: #{error.to_s}" }

Note that you must use the .try method and not the .[] method, since that skips the intermediate Result object and just returns the value. If you want to use the .[] method and also have errors be raised rather than captured in Failure, then you can consider using the :maybe extension instead.

dry-monads Do notation

This can be useful with do notation in dry-monads.

require 'dry/types'
require 'dry/monads'
Types = Dry.Types()
Dry::Types.load_extensions(:monads)

class AddTen
  include Dry::Monads[:result, :do]

  def call(input)
    integer = yield Types::Coercible::Integer.try(input)

    Success(integer + 10)
  end
end

add_ten = AddTen.new

add_ten.call(10)
# => Success(20)

add_ten.call('integer')
# => Failure([#<Dry::Types::CoercionError: invalid value for Integer(): "integer">, "integer"])