Skip to content

Instantly share code, notes, and snippets.

@flash-gordon
Created April 21, 2016 20:54
Show Gist options
  • Save flash-gordon/446d38a1c7295e1b9ffcbe1302741522 to your computer and use it in GitHub Desktop.
Save flash-gordon/446d38a1c7295e1b9ffcbe1302741522 to your computer and use it in GitHub Desktop.
module Dry
module Monad
class Either
attr_reader :right, :left
def ==(other)
other.is_a?(Either) && right == other.right && left == other.left
end
class Right < Either
alias_method :value, :right
def initialize(right)
@right = right
end
def bind(proc = nil)
if block_given?
yield(value)
else
proc.call(value)
end
end
alias_method :>>, :bind
def fmap(proc = nil, &block)
Right.new(bind(&(proc || block)))
end
def alt(val = nil)
self
end
def to_s
"Right(#{value.inspect})"
end
alias_method :inspect, :to_s
def to_maybe
Maybe::Some.new(value)
end
end
class Left < Either
alias_method :value, :left
def initialize(left)
@left = left
end
def bind(proc = nil)
self
end
def fmap
self
end
def alt(val = nil)
if block_given?
if val.nil?
yield(value)
else
raise ArgumentError.new('You can pass a block or a value, not both')
end
else
val
end
end
def to_s
"Left(#{value.inspect})"
end
alias_method :inspect, :to_s
def to_maybe
Maybe::None.instance
end
end
module Mixin
Right = Right
Left = Left
def Right(value)
Right.new(value)
end
def Left(value)
Left.new(value)
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment