ribimaybe 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTI2MGNiZjZlOWJkYzA4ZWYxZTQ2ZDJlN2RkODBkNGM3Y2Q0YzljMw==
5
+ data.tar.gz: !binary |-
6
+ NDdjZThjMmNlMTI2MjBkMTVjN2Y4MGNmZmNmMTdkNGZmZmY2MWY0Mw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OWI1Yzk3OTEzZjE5ZThjMDMwNWExMGNlOGJjNmE3MmViYTMxNTc1Nzc5N2E0
10
+ YTkzZjM4YjNkYTFiMzJjZTVmMjI5ODJiZjgwOTg2N2I3ZjE2Mzc3MmQ5YzQz
11
+ ODhiODdkM2YxNTU4YTZiNzI1ZTEwYzMwOGZkZjQ2Zjg4ZWEzY2I=
12
+ data.tar.gz: !binary |-
13
+ ZTY0OTY3ZWJkZDhiMDRlNWRmNjJkZWE4NWM0MTMxMzIyODVmOTNiYmU3NTlh
14
+ ODk1OWY3NTFhYmEyOWI1MmUwMjhkZDUyZTVhOTBiOGM5ZmZkMDdkZmNkMTNi
15
+ MTQxZGU2ZjNkNTg2MWMxZmM4MTQxYTYwZTQ3OTgzMWEwZjlmNzY=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ script:
5
+ - bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+ gem "contracts", "~> 0.4"
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 unsymbol
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # Ribimaybe
2
+
3
+ ![](maybe.gif)
4
+
5
+ A tiny Ruby library that provides a Maybe datatype which is a Functor,
6
+ Applicative Functor and Monad instance.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'ribimaybe'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install ribimaybe
21
+
22
+ ## Usage
23
+
24
+ This is a small library and so it doesn't offer lots of creature comforts. The
25
+ one escape hatch it does offer is the ability to convert `nil` into `Nothing`.
26
+
27
+ ``` ruby
28
+ include Ribimaybe::Maybe
29
+
30
+ Maybe(42) # => Just(42)
31
+ Maybe(nil) # => Nothing
32
+ ```
33
+
34
+ And that's it, once you have lifted your value into a `Maybe` you can treat it
35
+ as a `Functor`, `Applicative Functor` or `Monad`. If you want to pull your value
36
+ out of a `Maybe`, we got you covered too.
37
+
38
+ ``` ruby
39
+ Just(42).maybe(false) { |x| x == 42 } # => true
40
+ Nothing.maybe(false) { |x| x == 42 } # => false
41
+ ```
42
+
43
+ ### Functor [\[info\]](http://learnyouahaskell.com/functors-applicative-functors-and-monoids)
44
+
45
+ ``` ruby
46
+ include Ribimaybe::Maybe
47
+
48
+ # Apply functions within Maybe and retain structure.
49
+ Just(42).map { |x| x * x } # => Just(1764)
50
+ Nothing.map { |x| x * x } # => Nothing
51
+ ```
52
+
53
+ ### Applicative Functor [\[info\]](http://learnyouahaskell.com/functors-applicative-functors-and-monoids)
54
+
55
+ ``` ruby
56
+ include Ribimaybe::Maybe
57
+
58
+ # Wrap functions inside functors and apply them to other functors!
59
+ Just do |x|
60
+ x * x
61
+ end.apply(pure(42)) # => Just(1764)
62
+
63
+ Just do |x|
64
+ x * x
65
+ end.apply(Nothing) # => Nothing
66
+ ```
67
+
68
+ ### Monad [\[info\]](http://www.learnyouahaskell.com/a-fistful-of-monads)
69
+
70
+ ``` ruby
71
+ include Ribimaybe::Maybe
72
+
73
+ # Chain together computations and pretend you're a Haskeller.
74
+ Just(42).bind do |x|
75
+ rturn(x - 21)
76
+ end.bind do |x|
77
+ rturn(x * 2)
78
+ end # => Just(42)
79
+
80
+ # You guessed it! If have Nothing, you get Nothing.
81
+ Nothing.bind do |x|
82
+ rturn(x * x)
83
+ end # => Nothing
84
+ ```
85
+ ## Contributing
86
+
87
+ 1. Fork it
88
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
89
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
90
+ 4. Push to the branch (`git push origin my-new-feature`)
91
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core"
3
+ require "rspec/core/rake_task"
4
+ RSpec::Core::RakeTask.new(:default) do |spec|
5
+ spec.pattern = FileList["spec/**/*_spec.rb"]
6
+ end
data/lib/ribimaybe.rb ADDED
@@ -0,0 +1,216 @@
1
+ require "contracts"
2
+
3
+ module Ribimaybe
4
+ VERSION = "0.0.1"
5
+
6
+ module Maybe
7
+ include Contracts
8
+
9
+ module Nothing
10
+ include Contracts
11
+
12
+ # Nothing string representation.
13
+ #
14
+ def self.to_s
15
+ "Nothing"
16
+ end
17
+
18
+ # No operation. Always returns the default value.
19
+ #
20
+ Contract Any, Proc => Any
21
+ def self.maybe(default, &_)
22
+ default
23
+ end
24
+
25
+ # No operation. Always returns Nothing.
26
+ #
27
+ Contract Proc => Nothing
28
+ def self.map(&_)
29
+ self
30
+ end
31
+
32
+ # No operation. Always returns Nothing.
33
+ #
34
+ Contract Any => Nothing
35
+ def self.apply(_)
36
+ self
37
+ end
38
+
39
+ # No operation. Always returns Nothing.
40
+ #
41
+ Contract Proc => Nothing
42
+ def self.bind(&_)
43
+ self
44
+ end
45
+ end
46
+
47
+ class Just
48
+ include Contracts
49
+
50
+ def initialize(value)
51
+ @value = value
52
+ end
53
+
54
+ def to_s
55
+ "Just(#{@value.inspect})"
56
+ end
57
+
58
+ # Compares a Just to another Maybe.
59
+ #
60
+ # ==== Attributes
61
+ #
62
+ # * +other+ - The other Maybe value.
63
+ #
64
+ # ==== Examples
65
+ #
66
+ # Just(1) == Just(1) # => true
67
+ # Just(1) == Just(2) # => false
68
+ # Just(1) == Nothing # => false
69
+ #
70
+ Contract Or[Nothing, Just] => Bool
71
+ def ==(other)
72
+ other.maybe(false) do |value|
73
+ @value == value
74
+ end
75
+ end
76
+
77
+ # Fetches a value out of a Just and returns the application
78
+ # of fn to the internal value.
79
+ #
80
+ # ==== Attributes
81
+ #
82
+ # * +_+ - Irrelevant default.
83
+ # * +fn+ - Function to be applied inside our Just.
84
+ #
85
+ # ==== Examples
86
+ #
87
+ # Just(1).maybe(false) { |x| x == 1 } # => true
88
+ # Just(1).maybe(42) { |x| x } # => 1
89
+ #
90
+ Contract Any, Proc => Any
91
+ def maybe(_, &fn)
92
+ fn.(@value)
93
+ end
94
+
95
+ # Applies fn to a value inside Just and re-wraps it in another Just.
96
+ #
97
+ # ==== Attributes
98
+ #
99
+ # * +fn+ - Function to be applied inside Just.
100
+ #
101
+ # ==== Examples
102
+ #
103
+ # Just(1).map { |x| x + 1 } # => Just(2)
104
+ #
105
+ Contract Proc => Just
106
+ def map(&fn)
107
+ Just.new(fn.(@value))
108
+ end
109
+
110
+ # Applies fn inside Just to a value in another Just and re-wraps the
111
+ # result in another Just.
112
+ #
113
+ # ==== Attributes
114
+ #
115
+ # * +value+ - Maybe whose value will be use in function application.
116
+ #
117
+ # ==== Examples
118
+ #
119
+ # Just do |x|
120
+ # x + x
121
+ # end.apply(Just(1)) # => Just(2)
122
+ #
123
+ Contract Or[Nothing, Just] => Or[Nothing, Just]
124
+ def apply(value)
125
+ value.map { |v| @value.(v) }
126
+ end
127
+
128
+ # Applies fn to value inside Just (note contract constraint).
129
+ #
130
+ # ==== Attributes
131
+ #
132
+ # * +fn+ - Function to be applied inside our Just.
133
+ #
134
+ # ==== Examples
135
+ #
136
+ # Just(1).bind do |x|
137
+ # rturn(x + x)
138
+ # end # => Just(2)
139
+ #
140
+ Contract Proc => Just
141
+ def bind(&fn)
142
+ fn.(@value)
143
+ end
144
+ end
145
+
146
+ # Converts nil to Nothing or lifts value into a Just. Pass either a block
147
+ # or a function.
148
+ #
149
+ # ==== Attributes
150
+ #
151
+ # * +value+ - Value to be wrapped.
152
+ # * +fn+ - Block or function to be wrapped.
153
+ #
154
+ # ==== Examples
155
+ #
156
+ # Maybe(nil) # => Nothing
157
+ # Maybe(1) # => Just(1)
158
+ # Maybe { |x| x } # => Just(#<Proc:0x007fdecc03a478@(irb):6>)
159
+ #
160
+ Contract Any, Or[nil, Proc] => Or[Nothing, Just]
161
+ def Maybe(value = nil, &fn)
162
+ (value || fn) ? Just(value || fn) : Nothing
163
+ end
164
+
165
+ # Wraps a value or a function in a Just or returns a Nothing.
166
+ #
167
+ # ==== Attributes
168
+ #
169
+ # * +value+ - Value to be wrapped.
170
+ # * +fn+ - Block or function to be wrapped.
171
+ #
172
+ # ==== Examples
173
+ #
174
+ # Just(nil) # => Nothing
175
+ # Just(1) # => Just(1)
176
+ # Just { |x| x } # => Just(#<Proc:0x007fdecc03a478@(irb):6>)
177
+ #
178
+ Contract Any, Or[nil, Proc] => Or[Nothing, Just]
179
+ def Just(value = nil, &fn)
180
+ return Nothing unless (value || fn)
181
+ Just.new(value || fn)
182
+ end
183
+
184
+ # Wraps a value in a Just or returns a Nothing.
185
+ #
186
+ # ==== Attributes
187
+ #
188
+ # * +value+ - Value to be wrapped.
189
+ #
190
+ # ==== Examples
191
+ #
192
+ # pure(nil) # => Nothing
193
+ # pure(1) # => Just(1)
194
+ #
195
+ Contract Any => Or[Nothing, Just]
196
+ def pure(value)
197
+ Maybe(value)
198
+ end
199
+
200
+ # Wraps a value in a Just or returns a Nothing.
201
+ #
202
+ # ==== Attributes
203
+ #
204
+ # * +value+ - Value to be wrapped.
205
+ #
206
+ # ==== Examples
207
+ #
208
+ # rturn(nil) # => Nothing
209
+ # rturn(1) # => Just(1)
210
+ #
211
+ Contract Any => Or[Nothing, Just]
212
+ def rturn(value)
213
+ pure(value)
214
+ end
215
+ end
216
+ end
data/maybe.gif ADDED
Binary file
data/ribimaybe.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "ribimaybe"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ribimaybe"
8
+ spec.version = Ribimaybe::VERSION
9
+ spec.authors = ["unsymbol"]
10
+ spec.email = ["hello@philipcunningham.org"]
11
+ spec.description = "Maybe Functor, Applicative and Monad"
12
+ spec.summary = "A tiny Ruby library that provides a Maybe datatype which is a Functor, Applicative Functor and Monad instance."
13
+ spec.homepage = "https://github.com/unsymbol/ribimaybe"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "pry"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec"
25
+ end
@@ -0,0 +1,38 @@
1
+ require "spec_helper"
2
+ include Ribimaybe::Maybe
3
+
4
+ describe "Applicative Instance" do
5
+ describe "#pure" do
6
+ context "when i provide a nil" do
7
+ it "should give me back nothing" do
8
+ result = pure(nil)
9
+ expect(result).to eq Nothing
10
+ end
11
+ end
12
+
13
+ context "when i provide a value" do
14
+ it "should wrap the value" do
15
+ result = pure(42)
16
+ expect(result).to eq Just(42)
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "#apply" do
22
+ context "when i have nothing" do
23
+ it "should give me back nothing" do
24
+ result = Nothing.apply Just(42)
25
+ expect(result).to eq Nothing
26
+ end
27
+ end
28
+
29
+ context "when i something containing a fn" do
30
+ it "should be apply to apply that fn to something" do
31
+ result = Just do |x|
32
+ x + x
33
+ end.apply Just(21)
34
+ expect(result).to eq Just(42)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+ include Ribimaybe::Maybe
3
+
4
+ describe "Functor Instance" do
5
+ describe "#map" do
6
+ context "when i have nothing" do
7
+ it "should give me back nothing" do
8
+ result = Nothing.map { |x| x + 1 }
9
+ expect(result).to eq Nothing
10
+ end
11
+ end
12
+
13
+ context "when i have something" do
14
+ it "should apply the fn and we-wrap the value" do
15
+ result = Just(41).map { |x| x + 1 }
16
+ expect(result).to eq Just(42)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+ include Ribimaybe::Maybe
3
+
4
+ describe Ribimaybe::Maybe do
5
+ describe ".maybe" do
6
+ context "when i have nothing" do
7
+ it "should give me back a default" do
8
+ result = Nothing.maybe(42) { |x| x + 1 }
9
+ expect(result).to eq 42
10
+ end
11
+ end
12
+
13
+ context "when i have something" do
14
+ it "should give me back something" do
15
+ result = Just(42).maybe(1) { |x| x }
16
+ expect(result).to eq 42
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+ include Ribimaybe::Maybe
3
+
4
+ describe "Monad Instance" do
5
+ describe "#rturn" do
6
+ context "when i provide a nil" do
7
+ it "should give me back nothing" do
8
+ result = rturn(nil)
9
+ expect(result).to eq Nothing
10
+ end
11
+ end
12
+
13
+ context "when i provide a value" do
14
+ it "should wrap the value" do
15
+ result = rturn(42)
16
+ expect(result).to eq Just(42)
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "#bind" do
22
+ context "when i have nothing" do
23
+ it "should give me back nothing" do
24
+ result = Nothing.bind do |x|
25
+ rturn x + x
26
+ end
27
+ expect(result).to eq Nothing
28
+ end
29
+ end
30
+
31
+ context "when i something containing a fn" do
32
+ it "should be apply to apply that fn to something" do
33
+ result = Just(21).bind do |x|
34
+ rturn x + x
35
+ end
36
+ expect(result).to eq Just(42)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
2
+
3
+ require "bundler/setup"
4
+ require "pry"
5
+ require "ribimaybe"
6
+ require "rubygems"
7
+
8
+ RSpec.configure do |config|
9
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ribimaybe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - unsymbol
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Maybe Functor, Applicative and Monad
70
+ email:
71
+ - hello@philipcunningham.org
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .travis.yml
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - lib/ribimaybe.rb
83
+ - maybe.gif
84
+ - ribimaybe.gemspec
85
+ - spec/applicative_functor_spec.rb
86
+ - spec/functor_spec.rb
87
+ - spec/maybe_spec.rb
88
+ - spec/monad_instance_spec.rb
89
+ - spec/spec_helper.rb
90
+ homepage: https://github.com/unsymbol/ribimaybe
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.1.11
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: A tiny Ruby library that provides a Maybe datatype which is a Functor, Applicative
114
+ Functor and Monad instance.
115
+ test_files:
116
+ - spec/applicative_functor_spec.rb
117
+ - spec/functor_spec.rb
118
+ - spec/maybe_spec.rb
119
+ - spec/monad_instance_spec.rb
120
+ - spec/spec_helper.rb