dry-monads

v1.8
  1. Introduction
  2. Getting started
  3. Maybe
  4. Result
  5. Do notation
  6. Try
  7. List
  8. Task
  9. Validated
  10. Case equality
  11. Tracing failures
  12. Pattern matching
  13. Unit

TOC

  1. Matching Result values
  2. Matching Maybe
  3. Matching List
  4. Matching array values

Pattern matching

Ruby 2.7 introduces pattern matching, it is nicely supported by dry-monads 1.3+.

Matching Result values

# presumably you do it in a class with `include Dry::Monads[:result]`

case value
in Success(Integer => x)
  # x is bound to an integer
in Success[:created, user]
  # user is bound to the second member
in Success(Date | Time)
  # date or time object
in Success[1, *]
  # any array starting with 1
in Success(String => s) if s.size < 100
  # only if `s` is short enough
in Success(counter: Integer)
  # matches Success(counter: 50)
  # doesn't match Success(counter: 50, extra: 50)
in Success(user: User, account: Account => user_account)
  # matches Success(user: User.new(...), account: Account.new(...), else: ...)
  # user_account is bound to the value of the `:account` key
in Success()
  # corresponds to Success(Unit)
in Success(user:, **rest)
  # matches Success(user: User.new, other_key: "value")
in Success(_)
  # general success
in Failure[:user_not_found]
  # matches Failure([:user_not_found]) or Failure[:user_not_found]
in Failure[error_code, *payload]
  # ...
end

In the snippet above, the patterns will be tried sequentially. If value doesn't match any pattern, an error will be thrown.

Matching Maybe

case value
in Some(Integer => x) if x > 0
  # x is a positive integer
in Some(Float | String)
  # ...
in None
  # ...
end

Matching List

case value
in List[Integer]
  # any list of size 1 with an integer
in List[1, 2, 3, *]
  # list with size >= 3 starting with 1, 2, 3
in List[]
  # empty list
end

Matching array values

dry-monads treats all wrapped array values as tuples rather than lists.
For example, this will not work:

Success([1, 2, 3]) in Success(numbers) # => no match!

But this will:

Success([1, 2, 3]) in Success(one, two, three)

And this will too:

Success([1, 2, 3]) in Success[1, 2 ,3]

To capture an array value, use *:

Success([1, 2, 3]) in Success(*numbers)

At least for Failure values, people use tuples more often; this is why dry-monads treats all arrays as tuples. We could make Success/Failure behaviors different, but this would be even more unexpected.