Skip to content

Instantly share code, notes, and snippets.

@nuttycom
Created March 27, 2015 20:16
Show Gist options
  • Save nuttycom/83297cca6fda0afdb6d9 to your computer and use it in GitHub Desktop.
Save nuttycom/83297cca6fda0afdb6d9 to your computer and use it in GitHub Desktop.
Maybe (Ruby)
require 'flow/common/function'
class Maybe
include Enumerable
def self.just(v)
Maybe.new(->(if_nothing, if_just) { if_just.call(v) })
end
def self.nothing
@nothing ||= Maybe.new(->(if_nothing, if_just) { if_nothing.call })
end
def self.of(v)
v.nil? ? nothing : just(v)
end
def self.of_nonblank(v)
(v.nil? || v.strip == '') ? nothing : just(v)
end
def self.when(bool, &v)
bool ? just(v.call) : nothing
end
def fold(if_nothing, if_just)
@cata.call(if_nothing, if_just)
end
def map(&f)
@cata.call(->{ self }, ->(v){ Maybe.just(f.call(v)) })
end
def bind(&f)
@cata.call(->{ self }, ->(v){ f.call(v) })
end
def join
raise "Wrapped value is not a Maybe" unless self.all?{|v| v.is_a?(Maybe)}
bind(&Function::ID)
end
def is_nothing?
@cata.call(->{ true }, ->(v){ false })
end
def is_just?
!is_nothing?
end
def or_else(other_maybe)
@cata.call(->{ other_maybe }, ->(v){ self })
end
def or_else_lazy(&f)
@cata.call(f, ->(v){ self })
end
def or_default(v)
@cata.call(->{ v }, ->(v0){ v0 })
end
def or_lazy(&f)
@cata.call(f, ->(v0){ v0 })
end
def or_nil
or_default(nil)
end
def or_die
or_lazy { raise "Maybe value was Nothing!" }
end
def xor(other_maybe)
@cata.call(
->{ other_maybe },
->(v){ other_maybe.fold(->{ self }, ->(_){ Maybe.nothing }) }
)
end
def filter(&f)
@cata.call(->{ self }, ->(v){ f(v) ? self : Maybe.nothing })
end
def each(&block)
@cata.call(->{ nil }, block)
end
def hash
@cata.call(->{ 23 }, ->(v){ -23 ^ v.hash })
end
def eql?(other)
case other
when Maybe then @cata.call(
->{ other.is_nothing? },
->(v){ other.fold(->{ false }, ->(v0){ v.eql?(v0) }) }
)
else false
end
end
alias == eql?
private
def initialize(cata)
@cata = cata
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment