Class: Funkr::Types::Maybe
- Extended by:
- Applicative::ClassMethods, Monad::ClassMethods, Monoid::ClassMethods
- Includes:
- Alternative, Applicative, Functor, Categories, Monad, Monoid
- Defined in:
- lib/funkr/types/maybe.rb
Overview
Algebraïc Data Type representing the possibility of a missing value : nothing. It cleanly replace the ‘nil’ paradigm often found in ruby code, and often leading to bugs. The Maybe type belongs to multiple categories, making it extremly expressive to use (functor, applicative, alternative, monad, monoid … !).
You will get maximum performance and maximum expressiveness if you can use provided high level functions (map, apply, or_else, …) instead of pattern-matching yourself.
Constant Summary
Constants inherited from ADT
Class Method Summary collapse
-
.box(value) ⇒ Object
Box nil as nothing, and the rest as just x.
-
.concat(maybes) ⇒ Object
- concat
- Maybe a
-
-> [a] The Maybe.concat function takes a list of Maybes and returns a list of all the Just values.
Instance Method Summary collapse
- #apply(to) ⇒ Object
- #bind(&block) ⇒ Object
- #map(&block) ⇒ Object
- #mplus(m_y) ⇒ Object
- #or_else(&block) ⇒ Object
-
#unbox(default = nil) ⇒ Object
Unbox a maybe value.
-
#unsafe_content ⇒ Object
unsafe access to content, for performance purpose only.
Methods inherited from ADT
adt, #initialize, #match, matcher, #to_s, #unsafe_const, #unsafe_data
Constructor Details
This class inherits a constructor from Funkr::ADT
Class Method Details
.box(value) ⇒ Object
Box nil as nothing, and the rest as just x
137 138 139 140 |
# File 'lib/funkr/types/maybe.rb', line 137 def self.box(value) if value.nil? then self.nothing else self.just(value) end end |
.concat(maybes) ⇒ Object
- concat
- Maybe a
-
-> [a]
The Maybe.concat function takes a list of Maybes and returns
a list of all the Just values.
145 146 147 148 149 150 151 152 |
# File 'lib/funkr/types/maybe.rb', line 145 def self.concat(maybes) maybes.inject([]) do |a, e| e.match do |on| on.just{|v| a + [v]} on.nothing{ a } end end end |
Instance Method Details
#apply(to) ⇒ Object
Maybe can be made an applicative functor, for example :
f = Maybe.curry_lift_proc{|x,y| x + y}
a = Maybe.just(3)
b = Maybe.just(4)
c = Maybe.nothing
f.apply(a).apply(b) => Just 7
f.apply(a).apply(c) => Nothing
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/funkr/types/maybe.rb', line 54 def apply(to) # This implementation isn't safe but is a bit faster than the # safe one. A safe implementation would be as follow : # self.match do |f_on| # f_on.just do |f| # to.match do |t_on| # t_on.just {|t| self.class.unit(f.call(t)) } # t_on.nothing { to } # end # end # f_on.nothing { self } # end if self.just? and to.just? then self.class.unit(self.unsafe_content.call(to.unsafe_content)) else self.class.nothing end end |
#bind(&block) ⇒ Object
103 104 105 106 107 108 109 110 111 112 |
# File 'lib/funkr/types/maybe.rb', line 103 def bind(&block) # This implementation isn't safe but is a bit faster than the # safe one. A safe implementation would be as follow : # self.match do |on| # on.just {|v| yield(v)} # on.nothing {self} # end if self.just? then yield(self.unsafe_content) else self end end |
#map(&block) ⇒ Object
31 32 33 34 35 36 37 38 39 40 |
# File 'lib/funkr/types/maybe.rb', line 31 def map(&block) # This implementation isn't safe but is a bit faster than the # safe one. A safe implementation would be as follow : # self.match do |on| # on.just {|v| self.class.just(yield(v))} # on.nothing { self } # end if self.just? then self.class.just(yield(unsafe_content)) else self end end |
#mplus(m_y) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/funkr/types/maybe.rb', line 86 def mplus(m_y) self.match do |x_on| x_on.nothing { m_y } x_on.just do |x| m_y.match do |y_on| y_on.nothing { self } y_on.just {|y| self.class.just(x.mplus(y))} end end end end |
#or_else(&block) ⇒ Object
74 75 76 77 78 79 |
# File 'lib/funkr/types/maybe.rb', line 74 def or_else(&block) self.match do |on| on.just {|v| self} on.nothing { yield } end end |
#unbox(default = nil) ⇒ Object
Unbox a maybe value. You must provide a default in case of nothing. This method is not as safe as the others, as it will escape the content from the Maybe type safety.
Maybe.just(5).unbox(:foobar) # => 5 Maybe.nothing.unbox(:foobar) # => :foobar
120 121 122 123 124 125 |
# File 'lib/funkr/types/maybe.rb', line 120 def unbox(default=nil) self.match do |on| on.just {|v| v } on.nothing { default } end end |
#unsafe_content ⇒ Object
unsafe access to content, for performance purpose only
134 |
# File 'lib/funkr/types/maybe.rb', line 134 def unsafe_content; self.unsafe_data.first; end |