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(_)
# 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.