monad-maybe 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +27 -0
- data/README.md +12 -0
- data/Rakefile +23 -0
- data/VERSION +1 -0
- data/lib/monad/maybe.rb +59 -0
- data/lib/monad/maybe/base.rb +26 -0
- data/lib/monad/maybe/just.rb +58 -0
- data/lib/monad/maybe/list.rb +72 -0
- data/lib/monad/maybe/nothing.rb +56 -0
- data/monad-maybe.gemspec +55 -0
- data/test/maybe.rb +48 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1ce465e91a7fa1eaf0d0ab623ea89f2e94fb1a19
|
4
|
+
data.tar.gz: 2e99082f613f330a0f70ba2366ee197b13e9a85c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4b9a853ff984432ca743f2855165b29945e7664231229fbfe9c21a4b98d63c91b86d1d209e4704f45d451b9f01eb50f4b114aacc65ba0edbd472cf1da8baa1fe
|
7
|
+
data.tar.gz: c8b2fe434cd8521497a3aa13138582d5c1a8363279a4346d0251f8a5be89eb5a0aa77a58791618710c282bd0842f2a5c4317a37855329aa45cfae155c63cd995
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
git (1.2.5)
|
5
|
+
jeweler (1.8.4)
|
6
|
+
bundler (~> 1.0)
|
7
|
+
git (>= 1.2.5)
|
8
|
+
rake
|
9
|
+
rdoc
|
10
|
+
json (1.8.0)
|
11
|
+
mustache (0.99.4)
|
12
|
+
rake (10.0.4)
|
13
|
+
rdoc (4.0.1)
|
14
|
+
json (~> 1.4)
|
15
|
+
redcarpet (2.3.0)
|
16
|
+
rocco (0.8.2)
|
17
|
+
mustache
|
18
|
+
redcarpet
|
19
|
+
test-unit (2.5.5)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
jeweler
|
26
|
+
rocco
|
27
|
+
test-unit
|
data/README.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
`monad-maybe`
|
2
|
+
=============
|
3
|
+
|
4
|
+
An Implementation of Haskell's Maybe Mondad
|
5
|
+
-------------------------------------------
|
6
|
+
|
7
|
+
This is an attempt to implement Haskell's Maybe monad in a Ruby-ish way with as little monkey patching as possible.
|
8
|
+
|
9
|
+
SEE ALSO
|
10
|
+
========
|
11
|
+
[andand](http://)
|
12
|
+
[Haskell's Maybe Monad](http://)
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'jeweler'
|
2
|
+
Jeweler::Tasks.new do |gem|
|
3
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
4
|
+
gem.name = "monad-maybe"
|
5
|
+
gem.summary = %Q{A Ruby implementation of Haskell's Maybe Monad}
|
6
|
+
gem.description = %Q{This is an attempt to implement Haskell's Maybe monad in a Ruby-ish way with as little monkey patching as possible.}
|
7
|
+
gem.email = "delon.newman@gmail.com"
|
8
|
+
gem.homepage = "https://github.com/delonnewman/monad-maybe"
|
9
|
+
gem.authors = ["Delon Newman"]
|
10
|
+
end
|
11
|
+
Jeweler::RubygemsDotOrgTasks.new
|
12
|
+
|
13
|
+
desc "Run tests in ./test"
|
14
|
+
task :test do
|
15
|
+
Dir['test/*.rb'].each do |test|
|
16
|
+
sh "ruby #{test}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Setup for development"
|
21
|
+
task :setup do
|
22
|
+
sh "bundle"
|
23
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.8.0
|
data/lib/monad/maybe.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative 'maybe/base'
|
2
|
+
require_relative 'maybe/just'
|
3
|
+
require_relative 'maybe/nothing'
|
4
|
+
require_relative 'maybe/list'
|
5
|
+
|
6
|
+
module Monad
|
7
|
+
module Maybe
|
8
|
+
module Enumerable
|
9
|
+
def to_maybe
|
10
|
+
first.maybe
|
11
|
+
end
|
12
|
+
|
13
|
+
def maybe_map
|
14
|
+
List.new(map{ |x| yield(x) })
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ::Array; include Enumerable end
|
19
|
+
class ::Range; include Enumerable end
|
20
|
+
|
21
|
+
class ::Object
|
22
|
+
def maybe
|
23
|
+
Just.new(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def maybe?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
def just?
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
def nothing?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class ::NilClass
|
40
|
+
def maybe
|
41
|
+
Nothing.instance.freeze
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def maybe(o)
|
46
|
+
o.maybe
|
47
|
+
end
|
48
|
+
|
49
|
+
def just(o)
|
50
|
+
Just.new(o)
|
51
|
+
end
|
52
|
+
|
53
|
+
def nothing
|
54
|
+
Nothing.instance
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
include Monad::Maybe
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Monad
|
2
|
+
module Maybe
|
3
|
+
class Base
|
4
|
+
attr_reader :value
|
5
|
+
|
6
|
+
def <<(obj)
|
7
|
+
to_list << obj
|
8
|
+
end
|
9
|
+
|
10
|
+
def maybe?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def maybe
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_list
|
19
|
+
List.new(to_a)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def initialize; end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Monad
|
2
|
+
module Maybe
|
3
|
+
#
|
4
|
+
# Wraps a non-nil object allows us to treat these
|
5
|
+
# objects as a Maybe while distinguishing them from
|
6
|
+
# a Nothing
|
7
|
+
#
|
8
|
+
class Just < Base
|
9
|
+
def initialize(value)
|
10
|
+
@value = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(method, *args)
|
14
|
+
Just.new(value.send(method, *args))
|
15
|
+
end
|
16
|
+
|
17
|
+
def unwrap(val)
|
18
|
+
value
|
19
|
+
end
|
20
|
+
|
21
|
+
def nothing?
|
22
|
+
false
|
23
|
+
end
|
24
|
+
|
25
|
+
def just?
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def nil?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def ==(other)
|
34
|
+
self === other || self.value == other
|
35
|
+
end
|
36
|
+
|
37
|
+
def ===(other)
|
38
|
+
other.just? && self.value == other.value
|
39
|
+
end
|
40
|
+
|
41
|
+
def equal?(other)
|
42
|
+
other.__id__ == self.__id__
|
43
|
+
end
|
44
|
+
|
45
|
+
def inspect
|
46
|
+
"just(#{value.inspect})"
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
Just.new(value.to_s)
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_a
|
54
|
+
[self]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Monad
|
2
|
+
module Maybe
|
3
|
+
class List
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(enum)
|
7
|
+
@enum = enum.map { |v| v.maybe? ? v : v.maybe }
|
8
|
+
end
|
9
|
+
|
10
|
+
def inspect
|
11
|
+
"#{to_a}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def maybe?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def <<(obj)
|
19
|
+
@enum << obj if obj.just?
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_a
|
24
|
+
@enum.to_a
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_maybe
|
28
|
+
first.maybe
|
29
|
+
end
|
30
|
+
|
31
|
+
def each
|
32
|
+
@enum.each do |x|
|
33
|
+
yield(x)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def map
|
38
|
+
e = []
|
39
|
+
each do |x|
|
40
|
+
e << yield(x)
|
41
|
+
end
|
42
|
+
List.new(e)
|
43
|
+
end
|
44
|
+
alias maybe_map map
|
45
|
+
|
46
|
+
def select
|
47
|
+
e = []
|
48
|
+
each do |x|
|
49
|
+
is_true = yield(x)
|
50
|
+
e << x if is_true
|
51
|
+
end
|
52
|
+
List.new(e)
|
53
|
+
end
|
54
|
+
|
55
|
+
def reject
|
56
|
+
select { |x| !yield(x) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def select_just
|
60
|
+
select { |x| x.just? }
|
61
|
+
end
|
62
|
+
|
63
|
+
def unwrap_map(default, &blk)
|
64
|
+
to_a.map { |x| blk ? blk.call(x.unwrap(default)) : x.unwrap(default) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def value_map(&blk)
|
68
|
+
to_a.map { |x| blk ? blk.call(x.value) : x.value }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Monad
|
4
|
+
module Maybe
|
5
|
+
#
|
6
|
+
# A better nil
|
7
|
+
#
|
8
|
+
class Nothing < Base
|
9
|
+
include ::Singleton
|
10
|
+
|
11
|
+
def method_missing(method, *args)
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def clone
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
'nothing'
|
21
|
+
end
|
22
|
+
|
23
|
+
def nil?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def nothing?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def just?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def unwrap(val)
|
36
|
+
val
|
37
|
+
end
|
38
|
+
|
39
|
+
def value
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_json(*args)
|
44
|
+
'null'
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_a
|
52
|
+
[]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/monad-maybe.gemspec
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "monad-maybe"
|
8
|
+
s.version = "0.8.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Delon Newman"]
|
12
|
+
s.date = "2013-06-17"
|
13
|
+
s.description = "This is an attempt to implement Haskell's Maybe monad in a Ruby-ish way with as little monkey patching as possible."
|
14
|
+
s.email = "delon.newman@gmail.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"Gemfile",
|
20
|
+
"Gemfile.lock",
|
21
|
+
"README.md",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"lib/monad/maybe.rb",
|
25
|
+
"lib/monad/maybe/base.rb",
|
26
|
+
"lib/monad/maybe/just.rb",
|
27
|
+
"lib/monad/maybe/list.rb",
|
28
|
+
"lib/monad/maybe/nothing.rb",
|
29
|
+
"monad-maybe.gemspec",
|
30
|
+
"test/maybe.rb"
|
31
|
+
]
|
32
|
+
s.homepage = "https://github.com/delonnewman/monad-maybe"
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubygems_version = "2.0.0"
|
35
|
+
s.summary = "A Ruby implementation of Haskell's Maybe Monad"
|
36
|
+
|
37
|
+
if s.respond_to? :specification_version then
|
38
|
+
s.specification_version = 4
|
39
|
+
|
40
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
41
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
42
|
+
s.add_development_dependency(%q<rocco>, [">= 0"])
|
43
|
+
s.add_development_dependency(%q<test-unit>, [">= 0"])
|
44
|
+
else
|
45
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
46
|
+
s.add_dependency(%q<rocco>, [">= 0"])
|
47
|
+
s.add_dependency(%q<test-unit>, [">= 0"])
|
48
|
+
end
|
49
|
+
else
|
50
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
51
|
+
s.add_dependency(%q<rocco>, [">= 0"])
|
52
|
+
s.add_dependency(%q<test-unit>, [">= 0"])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
data/test/maybe.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/monad/maybe'
|
3
|
+
|
4
|
+
class MaybeTest < Test::Unit::TestCase
|
5
|
+
def test_nothing
|
6
|
+
assert nil.maybe.nothing?
|
7
|
+
assert nil.maybe.value.nil?
|
8
|
+
assert_equal 'test', nil.maybe.unwrap('test')
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_just
|
12
|
+
assert 1.maybe.just?
|
13
|
+
assert_equal 1, 1.maybe.value
|
14
|
+
assert_equal 1, 1.maybe.unwrap('test')
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_to_a
|
18
|
+
assert_equal [1.maybe], 1.maybe.to_a
|
19
|
+
assert_equal [], nil.maybe.to_a
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_false
|
23
|
+
assert_equal false, false.maybe.value
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_nil_conversions
|
27
|
+
assert_equal nil.nil?, nil.maybe.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_class
|
31
|
+
assert_equal Nothing, nil.maybe.class
|
32
|
+
assert_equal Just, 1.maybe.class
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_list
|
36
|
+
xs = true.maybe << nil.maybe << 1.maybe << 3.maybe
|
37
|
+
assert_equal 3, xs.count
|
38
|
+
xs.each { |x| assert x.just? }
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_enumerable
|
42
|
+
assert_nothing_raised do
|
43
|
+
xs = (0..10).select { |n| n % 2 != 0 }
|
44
|
+
ys = (0..10).maybe_map { |n| n % 2 == 0 ? nil : n }.select_just.value_map
|
45
|
+
assert_equal xs.count, ys.count
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: monad-maybe
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Delon Newman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: jeweler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rocco
|
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: test-unit
|
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
|
+
description: This is an attempt to implement Haskell's Maybe monad in a Ruby-ish way
|
56
|
+
with as little monkey patching as possible.
|
57
|
+
email: delon.newman@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files:
|
61
|
+
- README.md
|
62
|
+
files:
|
63
|
+
- Gemfile
|
64
|
+
- Gemfile.lock
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- VERSION
|
68
|
+
- lib/monad/maybe.rb
|
69
|
+
- lib/monad/maybe/base.rb
|
70
|
+
- lib/monad/maybe/just.rb
|
71
|
+
- lib/monad/maybe/list.rb
|
72
|
+
- lib/monad/maybe/nothing.rb
|
73
|
+
- monad-maybe.gemspec
|
74
|
+
- test/maybe.rb
|
75
|
+
homepage: https://github.com/delonnewman/monad-maybe
|
76
|
+
licenses: []
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 2.0.0
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: A Ruby implementation of Haskell's Maybe Monad
|
98
|
+
test_files: []
|