---
title: Maybe
layout: gem-single
name: dry-monads
---

The `Maybe` monad is used when a series of computations could return `nil` at any point.

### `bind`

Applies a block to a monadic value. If the value is `Some` then calls the block passing the unwrapped value as an argument. Returns itself if the value is `None`.

```ruby
extend Dry::Monads[:maybe]

maybe_street = Maybe(user).bind do |u|
  Maybe(u.address).bind do |a|
    Maybe(a.street)
  end
end

# If user with address exists
# => Some("Street Address")
# If user or address is nil
# => None()

# You also can pass a proc to #bind

add_two = -> (x) { Maybe(x + 2) }

Maybe(5).bind(add_two).bind(add_two) # => Some(9)
Maybe(nil).bind(add_two).bind(add_two) # => None()

```

### `fmap`

Similar to `bind` but works with blocks/methods that returns unwrapped values (i.e. not `Maybe` instances).

```ruby
extend Dry::Monads[:maybe]

Maybe(10).fmap { |x| x + 5 }.fmap { |y| y * 2 }
# => Some(30)
```

In 1.x `Maybe#fmap` coerces `nil` values returned from blocks to `None`. This behavior will be changed in 2.0. This will be done because implicit coercion violates the functor laws which in order can lead to a surpising (not in a good sense) behavior. If you expect a block to return `nil`, use `Maybe#maybe` added in 1.3.

### `maybe`

Almost identical to `Maybe#fmap` but maps `nil` to `None`. This is similar to how the `&.` operator works in Ruby but does wrapping:

```ruby
extend Dry::Monads[:maybe]

Maybe(user).maybe(&:address).maybe(&:street)

# If user with address exists
# => Some("Street Address")
# If user or address is nil
# => None()
```

### `value!`

You always can extract the result by calling `value!`. It will raise an error if you call it on `None`. You can use `value_or` for safe unwrapping.

```ruby
extend Dry::Monads[:maybe]

Some(5).fmap(&:succ).value! # => 6

None().fmap(&:succ).value!
# => Dry::Monads::UnwrapError: value! was called on None

```

### `value_or`

Has one argument, unwraps the value in case of `Some` or returns the argument value back in case of `None`. It's a safe and recommended way of extracting values.

```ruby
extend Dry::Monads[:maybe]

add_two = -> (x) { Maybe(x + 2) }

Maybe(5).bind(add_two).value_or(0) # => 7
Maybe(nil).bind(add_two).value_or(0) # => 0

Maybe(nil).bind(add_two).value_or { 0 } # => 0
```

### `or`

The opposite of `bind`.

```ruby
extend Dry::Monads[:maybe]

add_two = -> (x) { Maybe(x + 2) }

Maybe(5).bind(add_two).or(Some(0)) # => Some(7)
Maybe(nil).bind(add_two).or(Some(0)) # => Some(0)

Maybe(nil).bind(add_two).or { Some(0) } # => Some(0)
```

There's an alias operator for `or`:

```ruby
extend Dry::Monads[:maybe]

None() | Some(1) | Some(2) # => Some(1)
```

### `and`

Two values can be chained using `.and`:

```ruby
extend Dry::Monads[:maybe]

Some(5).and(Some(10)) { |x, y| x + y } # => Some(15)
Some(5).and(None) { |x, y| x + y }     # => None()
None().and(Some(10)) { |x, y| x + y }  # => None()

Some(5).and(Some(10)) # => Some([5, 10])
Some(5).and(None())   # => None()
```

### `flatten`

To remove one level of nesting:

```ruby
extend Dry::Monads[:maybe]

Some(Some(10)).flatten # => Some(10)
Some(None()).flatten   # => None()
None().flatten         # => None()
```

### `to_result`

Maybe values can be converted to Result objects:

```ruby
extend Dry::Monads[:maybe, :result]

Some(10).to_result # => Success(10)
None().to_result # => Failure()
None().to_result(:error) # => Failure(:error)
None().to_result { :block_value } # => Failure(:block_value)
```

### `filter`

`Maybe#filter` runs a predicate against the wrapped value. Returns `None` if the result is false:

```ruby
Some(3).filter(&:odd?)  # => Some(3)
Some(3).filter(&:even?) # => None
# no block given
Some(3 == 5).filter     # => None
```
