Created
March 27, 2015 20:16
-
-
Save nuttycom/83297cca6fda0afdb6d9 to your computer and use it in GitHub Desktop.
Maybe (Ruby)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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