Demonstrate in your programming language the following:

Construct a Maybe Monad by writing the 'bind' function and the 'unit' (sometimes known as 'return') function for that Monad (or just use what the language already has implemented)
Make two functions, each which take a number and return a monadic number, e.g. Int -> Maybe Int and Int -> Maybe String
Compose the two functions with bind


A Monad is a single type which encapsulates several other types, eliminating boilerplate code. In practice it acts like a dynamically typed computational sequence, though in many cases the type issues can be resolved at compile time.

A Maybe Monad is a monad which specifically encapsulates the type of an undefined value.

class Maybe
  def initialize(value)
    @value = value
  end
 
  def map
    if @value.nil?
      self
    else
      Maybe.new(yield @value)
    end
  end
end
 
Maybe.new(3).map { |n| 2*n }.map { |n| n+1 }
#=> #<Maybe @value=7>
 
Maybe.new(nil).map { |n| 2*n }.map { |n| n+1 }
#=> #<Maybe @value=nil>
 
Maybe.new(3).map { |n| nil }.map { |n| n+1 }
#=> #<Maybe @value=nil>
 
# alias Maybe#new and write bind to be in line with task
 
class Maybe
  class << self
    alias :unit :new
  end
 
  def initialize(value)
    @value = value
  end
 
  def bind
    if @value.nil?
      self
    else
      yield @value
    end
  end
end
 
Maybe.unit(3).bind { |n| Maybe.unit(2*n) }.bind { |n| Maybe.unit(n+1) }
#=> #<Maybe @value=7>
 
Maybe.unit(nil).bind { |n| Maybe.unit(2*n) }.bind { |n| Maybe.unit(n+1) }
#=> #<Maybe @value=nil>
 