do_notation 0.2.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.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ coverage
3
+ doc
4
+ *.tmproj
5
+ *.gem
data/Manifest ADDED
@@ -0,0 +1,15 @@
1
+ lib/do_notation/monad.rb
2
+ lib/do_notation/monad_plus.rb
3
+ lib/do_notation/monads/array.rb
4
+ lib/do_notation/monads/maybe.rb
5
+ lib/do_notation/monads/simulations.rb
6
+ lib/do_notation/rewriter.rb
7
+ lib/do_notation.rb
8
+ README.rdoc
9
+ test/array.rb
10
+ test/maybe.rb
11
+ test/monad_plus.rb
12
+ test/simulations.rb
13
+ test/spec_helper.rb
14
+ test/specs.rb
15
+ Manifest
data/README.rdoc ADDED
@@ -0,0 +1,42 @@
1
+ = Haskell-style monad do-notation for Ruby
2
+
3
+ Example:
4
+
5
+ require 'do_notation'
6
+
7
+ class Array
8
+ include Monad
9
+
10
+ def self.unit x
11
+ [x]
12
+ end
13
+
14
+ def bind &f
15
+ map(&f).inject([]){ |a,b| a+b }
16
+ end
17
+ end
18
+
19
+ Array.run do
20
+ x <- ["first", "second"]
21
+ y <- ["once", "twice"]
22
+
23
+ unit("#{x} cousin #{y} removed")
24
+ end
25
+
26
+ The above code returns the array:
27
+
28
+ ["first cousin once removed",
29
+ "first cousin twice removed",
30
+ "second cousin once removed",
31
+ "second cousin twice removed"]
32
+
33
+ For more examples, see the test suite.
34
+
35
+ == Installation
36
+
37
+ There's a gem hosted on Github, so follow the setup instructions
38
+ at http://gems.github.com and then run:
39
+
40
+ sudo gem install aanand-ruby-do-notation
41
+
42
+ By Aanand Prasad (aanand.prasad@gmail.com)
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'spec/rake/spectask'
2
+
3
+ spec_list = FileList['test/*.rb']
4
+
5
+ task :default => :spec
6
+
7
+ desc "Run all specs"
8
+ Spec::Rake::SpecTask.new('spec') do |t|
9
+ t.spec_files = spec_list
10
+ end
11
+
12
+ desc "Run all specs with RCov"
13
+ Spec::Rake::SpecTask.new('rcov') do |t|
14
+ t.spec_files = spec_list
15
+ t.rcov = true
16
+ end
17
+
18
+ begin
19
+ require 'jeweler'
20
+ Jeweler::Tasks.new do |gemspec|
21
+ gemspec.name = "do_notation"
22
+ gemspec.summary = 'Haskell-style monad do-notation for Ruby'
23
+ gemspec.description = 'Haskell-style monad do-notation for Ruby'
24
+ gemspec.email = 'aanand.prasad@gmail.com'
25
+ gemspec.homepage = 'http://github.com/aanand/do_notation'
26
+ gemspec.authors = ["Aanand Prasad"]
27
+ gemspec.add_dependency('ParseTree')
28
+ gemspec.add_dependency('ruby2ruby', '1.1.9')
29
+ end
30
+ rescue LoadError
31
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
32
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,67 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
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 = %q{do-notation}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Aanand Prasad"]
12
+ s.date = %q{2009-09-29}
13
+ s.description = %q{Haskell-style monad do-notation for Ruby}
14
+ s.email = %q{aanand.prasad@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "Manifest",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "lib/do_notation.rb",
24
+ "lib/do_notation/monad.rb",
25
+ "lib/do_notation/monad_plus.rb",
26
+ "lib/do_notation/monads/array.rb",
27
+ "lib/do_notation/monads/maybe.rb",
28
+ "lib/do_notation/monads/simulations.rb",
29
+ "lib/do_notation/rewriter.rb",
30
+ "ruby-do-notation.gemspec",
31
+ "test/array.rb",
32
+ "test/maybe.rb",
33
+ "test/monad_plus.rb",
34
+ "test/simulations.rb",
35
+ "test/spec_helper.rb",
36
+ "test/specs.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/aanand/do-notation}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.4}
42
+ s.summary = %q{Haskell-style monad do-notation for Ruby}
43
+ s.test_files = [
44
+ "test/array.rb",
45
+ "test/maybe.rb",
46
+ "test/monad_plus.rb",
47
+ "test/simulations.rb",
48
+ "test/spec_helper.rb",
49
+ "test/specs.rb"
50
+ ]
51
+
52
+ if s.respond_to? :specification_version then
53
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
54
+ s.specification_version = 3
55
+
56
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
57
+ s.add_runtime_dependency(%q<ParseTree>, [">= 0"])
58
+ s.add_runtime_dependency(%q<ruby2ruby>, ["= 1.1.9"])
59
+ else
60
+ s.add_dependency(%q<ParseTree>, [">= 0"])
61
+ s.add_dependency(%q<ruby2ruby>, ["= 1.1.9"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<ParseTree>, [">= 0"])
65
+ s.add_dependency(%q<ruby2ruby>, ["= 1.1.9"])
66
+ end
67
+ end
@@ -0,0 +1,24 @@
1
+ module Monad
2
+ module ClassMethods
3
+ def run &block
4
+ eval(ruby_for(block), block).call
5
+ end
6
+
7
+ def ruby_for block
8
+ @cached_ruby ||= {}
9
+ @cached_ruby[block.to_s] ||= "#{self.name}.instance_eval { #{Ruby2Ruby.new.process(Rewriter.new.process(block.to_method.to_sexp)[2])} }"
10
+ end
11
+ end
12
+
13
+ def bind_const &block
14
+ bind { |_| block.call() }
15
+ end
16
+
17
+ def >> n
18
+ bind_const { n }
19
+ end
20
+
21
+ def self.included m
22
+ m.extend ClassMethods
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ module MonadPlus
2
+ def guard p
3
+ if p
4
+ unit(mzero)
5
+ else
6
+ mzero
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ require 'do_notation/monad_plus'
2
+
3
+ class Array
4
+ include Monad
5
+
6
+ def self.unit x
7
+ [x]
8
+ end
9
+
10
+ def bind &f
11
+ map(&f).inject([]){ |a,b| a+b }
12
+ end
13
+
14
+ extend MonadPlus
15
+
16
+ def self.mzero
17
+ []
18
+ end
19
+
20
+ alias_method :mplus, :+
21
+ end
@@ -0,0 +1,31 @@
1
+ require 'do_notation/monad_plus'
2
+
3
+ class Maybe < Struct.new(:value)
4
+ include Monad
5
+
6
+ def self.unit value
7
+ self.new(value)
8
+ end
9
+
10
+ def bind &f
11
+ if value.nil?
12
+ self
13
+ else
14
+ f.call(value)
15
+ end
16
+ end
17
+
18
+ extend MonadPlus
19
+
20
+ def self.mzero
21
+ unit(nil)
22
+ end
23
+
24
+ def mplus m
25
+ if value.nil?
26
+ m
27
+ else
28
+ self
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,117 @@
1
+ # converted from Mauricio Fernandez's "Warm fuzzy things for random simulations":
2
+ # http://eigenclass.org/hiki/warm-fuzzy-things-for-random-simulations
3
+ # http://eigenclass.org/hiki.rb?c=plugin;plugin=attach_download;p=warm-fuzzy-things-for-random-simulations;file_name=fuzzy-warm-simulations.rb
4
+
5
+ module PRNG
6
+ def next_state(s); (69069 * s + 5) % (2**32) end
7
+ end
8
+
9
+ class Simulation
10
+ extend PRNG
11
+ include Monad
12
+
13
+ attr_reader :f
14
+
15
+ def initialize(&b)
16
+ @f = b
17
+ end
18
+
19
+ def self.unit(x)
20
+ new { |s| [x, s] }
21
+ end
22
+
23
+ def self.rand(n)
24
+ self.new do |s|
25
+ [s.abs % n, next_state(s)]
26
+ end
27
+ end
28
+
29
+ def bind(&b)
30
+ self.class.new do |s|
31
+ x, s = @f.call(s)
32
+ b.call(x).f.call(s)
33
+ end
34
+ end
35
+
36
+ def play(s = 12345)
37
+ @f.call(s).first
38
+ end
39
+ end
40
+
41
+ class Distribution
42
+ extend PRNG
43
+ include Monad
44
+
45
+ attr_reader :a
46
+
47
+ def initialize(a)
48
+ @a = a
49
+ end
50
+
51
+ def self.wrap(a)
52
+ new(a)
53
+ end
54
+
55
+ def self.unit(x)
56
+ wrap [[x, 1.0]]
57
+ end
58
+
59
+ def self.rand(n)
60
+ p = 1.0 / n
61
+ new((0...n).map{|i| [i, p]})
62
+ end
63
+
64
+ def bind(&b)
65
+ if @a.empty?
66
+ self.class.wrap([])
67
+ else
68
+ x, p = @a[0]
69
+ self.class.wrap(mulp(p, b.call(x)) + self.class.new(@a[1..-1]).bind(&b).a)
70
+ end
71
+ end
72
+
73
+ def play
74
+ h = Hash.new{|h, k| h[k] = 0.0}
75
+ @a.each{|x, p| h[x] += p}
76
+ h.to_a.sort_by{|x,| x}
77
+ end
78
+
79
+ private
80
+ def mulp(p, l)
81
+ l.a.map{|x, p1| [x, p * p1]}
82
+ end
83
+ end
84
+
85
+ class Expectation
86
+ extend PRNG
87
+ include Monad
88
+
89
+ attr_reader :f
90
+
91
+ def initialize(&b)
92
+ @f = b
93
+ end
94
+
95
+ def self.wrap(&proc)
96
+ new(&proc)
97
+ end
98
+
99
+ def self.unit(x)
100
+ wrap{ |f| f.call(x) }
101
+ end
102
+
103
+ def self.rand(n)
104
+ wrap do |k|
105
+ sum = (0..n-1).map{|x| k.call(x)}.inject{|s,x| s+x}
106
+ 1.0 * sum / n
107
+ end
108
+ end
109
+
110
+ def bind(&b)
111
+ self.class.wrap{|k| @f.call(lambda{|x| b.call(x).f.call(k)}) }
112
+ end
113
+
114
+ def play(x)
115
+ @f.call(lambda{|x1| x1 == x ? 1.0 : 0.0})
116
+ end
117
+ end
@@ -0,0 +1,63 @@
1
+ class Rewriter < SexpProcessor
2
+ def process_bmethod exp
3
+ type = exp.shift
4
+
5
+ exp.shift # throw away arguments
6
+
7
+ body = process(exp.shift)
8
+
9
+ if body[0] == :block
10
+ body.shift
11
+ else
12
+ body = s([*body])
13
+ end
14
+
15
+ s(:iter, s(:fcall, :proc), nil, *rewrite_assignments(body))
16
+ end
17
+
18
+ def rewrite_assignments exp
19
+ return [] if exp.empty?
20
+
21
+ head = exp.shift
22
+
23
+ if head.first == :call and head[1].first == :vcall and head[2] == :< and head[3].first == :array and head[3][1].last == :-@
24
+ var_name = head[1][1]
25
+ expression = head[3][1][1]
26
+
27
+ body = rewrite_assignments(exp)
28
+
29
+ if body.first.is_a? Symbol
30
+ body = [s(*body)]
31
+ end
32
+
33
+ [s(:iter,
34
+ s(:call, process(expression), :bind),
35
+ s(:dasgn_curr, var_name),
36
+ *body)]
37
+ elsif exp.empty?
38
+ [process(head)]
39
+ else
40
+ [s(:iter, s(:call, process(head) , :bind_const), nil ,
41
+ *rewrite_assignments(exp)) ]
42
+ end
43
+ end
44
+
45
+ def self.pp(obj, indent='')
46
+ return obj.inspect unless obj.is_a? Array
47
+ return '()' if obj.empty?
48
+
49
+ str = '(' + pp(obj.first, indent + ' ')
50
+
51
+ if obj.length > 1
52
+ str << ' '
53
+
54
+ next_indent = indent + (' ' * str.length)
55
+
56
+ str << obj[1..-1].map{ |o| pp(o, next_indent) }.join("\n#{next_indent}")
57
+ end
58
+
59
+ str << ')'
60
+
61
+ str
62
+ end
63
+ end
@@ -0,0 +1,12 @@
1
+ $: << File.dirname(__FILE__)
2
+
3
+ require 'rubygems'
4
+
5
+ gem 'ruby2ruby', '1.1.9'
6
+
7
+ require 'parse_tree'
8
+ require 'sexp_processor'
9
+ require 'ruby2ruby'
10
+
11
+ require 'do_notation/rewriter'
12
+ require 'do_notation/monad'
@@ -0,0 +1,59 @@
1
+
2
+ # Gem::Specification for Ruby-do-notation-0.2
3
+ # Originally generated by Echoe
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{ruby-do-notation}
7
+ s.version = "0.2"
8
+
9
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Aanand Prasad"]
13
+ s.date = %q{2008-06-20}
14
+ s.description = %q{Haskell-style monad do-notation for Ruby}
15
+ s.email = %q{aanand.prasad@gmail.com}
16
+ s.extra_rdoc_files = ["lib/do_notation/monad.rb", "lib/do_notation/monad_plus.rb", "lib/do_notation/monads/array.rb", "lib/do_notation/monads/maybe.rb", "lib/do_notation/monads/simulations.rb", "lib/do_notation/rewriter.rb", "lib/do_notation.rb", "README.markdown"]
17
+ s.files = ["lib/do_notation/monad.rb", "lib/do_notation/monad_plus.rb", "lib/do_notation/monads/array.rb", "lib/do_notation/monads/maybe.rb", "lib/do_notation/monads/simulations.rb", "lib/do_notation/rewriter.rb", "lib/do_notation.rb", "README.markdown", "test/array.rb", "test/maybe.rb", "test/monad_plus.rb", "test/simulations.rb", "test/spec_helper.rb", "test/specs.rb", "Manifest", "ruby-do-notation.gemspec"]
18
+ s.has_rdoc = true
19
+ s.homepage = %q{http://github.com/aanand/ruby-do-notation/tree/master}
20
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Ruby-do-notation", "--main", "README.markdown"]
21
+ s.require_paths = ["lib"]
22
+ s.rubyforge_project = %q{ruby-do-notation}
23
+ s.rubygems_version = %q{1.1.0}
24
+ s.summary = %q{Haskell-style monad do-notation for Ruby}
25
+
26
+ s.add_dependency(%q<ParseTree>, [">= 0"])
27
+ s.add_dependency(%q<ruby2ruby>, [">= 0"])
28
+ end
29
+
30
+
31
+ # # Original Rakefile source (requires the Echoe gem):
32
+ #
33
+ # require 'spec/rake/spectask'
34
+ #
35
+ # spec_list = FileList['test/*.rb']
36
+ #
37
+ # task :default => :test
38
+ #
39
+ # desc "Run all specs"
40
+ # Spec::Rake::SpecTask.new('spec') do |t|
41
+ # t.spec_files = spec_list
42
+ # end
43
+ #
44
+ # desc "Run all specs with RCov"
45
+ # Spec::Rake::SpecTask.new('rcov') do |t|
46
+ # t.spec_files = spec_list
47
+ # t.rcov = true
48
+ # end
49
+ #
50
+ # require 'echoe'
51
+ #
52
+ # Echoe.new('ruby-do-notation') do |p|
53
+ # p.author = 'Aanand Prasad'
54
+ # p.summary = 'Haskell-style monad do-notation for Ruby'
55
+ # p.email = 'aanand.prasad@gmail.com'
56
+ # p.url = 'http://github.com/aanand/ruby-do-notation/tree/master'
57
+ # p.version = '0.2'
58
+ # p.dependencies = ['ParseTree', 'ruby2ruby']
59
+ # end
data/test/array.rb ADDED
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'do_notation/monads/array'
3
+
4
+ describe "Array:" do
5
+ specify "all results are calculated and concatenated" do
6
+ array = Array.run do
7
+ x <- ["first", "second"]
8
+ y <- ["once", "twice"]
9
+
10
+ unit("#{x} cousin #{y} removed")
11
+ end
12
+
13
+ array.should == ["first cousin once removed",
14
+ "first cousin twice removed",
15
+ "second cousin once removed",
16
+ "second cousin twice removed"]
17
+ end
18
+ end
data/test/maybe.rb ADDED
@@ -0,0 +1,26 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'do_notation/monads/maybe'
3
+
4
+ describe "Maybe:" do
5
+ specify "one or more nils results in nil" do
6
+ maybe = Maybe.run do
7
+ x <- unit(1)
8
+ y <- unit(nil)
9
+
10
+ unit(x+y)
11
+ end
12
+
13
+ maybe.value.should == nil
14
+ end
15
+
16
+ specify "all non-nil results in complete calculation" do
17
+ maybe = Maybe.run do
18
+ x <- unit(1)
19
+ y <- unit(2)
20
+
21
+ unit(x+y)
22
+ end
23
+
24
+ maybe.value.should == 3
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'do_notation/monads/array'
3
+ require 'do_notation/monads/maybe'
4
+
5
+ describe "MonadPlus:" do
6
+ specify "mzero >>= f = mzero" do
7
+ Array.mzero.bind{ |x| unit(x+1) }.should == Array.mzero
8
+ Maybe.mzero.bind{ |x| unit(x+1) }.should == Maybe.mzero
9
+ end
10
+
11
+ specify "v >> mzero = mzero" do
12
+ ([1,2,3] >> Array.mzero).should == Array.mzero
13
+ (Maybe.unit(1) >> Maybe.mzero).should == Maybe.mzero
14
+ end
15
+
16
+ specify "mzero `mplus` m = m" do
17
+ Array.mzero.mplus([1,2,3]).should == [1,2,3]
18
+ Maybe.mzero.mplus(Maybe.unit(1)).should == Maybe.unit(1)
19
+ end
20
+
21
+ specify "m `mplus` mzero = m" do
22
+ [1,2,3].mplus(Array.mzero).should == [1,2,3]
23
+ Maybe.unit(1).mplus(Maybe.mzero).should == Maybe.unit(1)
24
+ end
25
+
26
+ specify "guard() prunes the execution tree" do
27
+ array = Array.run do
28
+ x <- [0,1,2,3]
29
+ y <- [0,1,2,3]
30
+ guard(x + y == 3)
31
+
32
+ unit([x,y])
33
+ end
34
+
35
+ array.should == [[0, 3], [1, 2], [2, 1], [3, 0]]
36
+ end
37
+ end
@@ -0,0 +1,46 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'do_notation/monads/simulations'
3
+
4
+ roll_3d6 = proc do
5
+ d1 <- rand(6)
6
+ d2 <- rand(6)
7
+ d3 <- rand(6)
8
+
9
+ unit(1+d1 + 1+d2 + 1+d3)
10
+ end
11
+
12
+ roll_3d6_b = proc do
13
+ d1 <- rand(6)
14
+ d2 <- rand(6)
15
+ d3 <- rand(6)
16
+
17
+ if [d1, d2, d3].include?(5)
18
+ run do
19
+ d4 <- rand(6)
20
+ unit(1+d1 + 1+d2 + 1+d3 + 1+d4)
21
+ end
22
+ else
23
+ unit(1+d1 + 1+d2 + 1+d3)
24
+ end
25
+ end
26
+
27
+ describe "Simulation" do
28
+ specify "generates correct answers" do
29
+ Simulation.run(&roll_3d6).play.should == 9
30
+ Simulation.run(&roll_3d6_b).play.should == 9
31
+ end
32
+ end
33
+
34
+ describe "Distribution" do
35
+ specify "generates correct answers" do
36
+ Distribution.run(&roll_3d6).play.inspect.should == "[[3, 0.00462962962962963], [4, 0.0138888888888889], [5, 0.0277777777777778], [6, 0.0462962962962963], [7, 0.0694444444444444], [8, 0.0972222222222222], [9, 0.115740740740741], [10, 0.125], [11, 0.125], [12, 0.115740740740741], [13, 0.0972222222222222], [14, 0.0694444444444444], [15, 0.0462962962962963], [16, 0.0277777777777778], [17, 0.0138888888888889], [18, 0.00462962962962963]]"
37
+ Distribution.run(&roll_3d6_b).play.inspect.should == "[[3, 0.00462962962962963], [4, 0.0138888888888889], [5, 0.0277777777777778], [6, 0.0462962962962963], [7, 0.0694444444444444], [8, 0.0833333333333333], [9, 0.0902777777777777], [10, 0.0902777777777778], [11, 0.0833333333333333], [12, 0.0694444444444445], [13, 0.0625000000000001], [14, 0.0601851851851853], [15, 0.0578703703703705], [16, 0.0555555555555557], [17, 0.0532407407407408], [18, 0.0462962962962964], [19, 0.0354938271604938], [20, 0.0239197530864198], [21, 0.0146604938271605], [22, 0.00771604938271605], [23, 0.00308641975308642], [24, 0.000771604938271605]]"
38
+ end
39
+ end
40
+
41
+ describe "Expectation" do
42
+ specify "generates correct answers" do
43
+ (1..21).collect { |x| Expectation.run(&roll_3d6).play(x) }.inspect.should == "[0.0, 0.0, 0.00462962962962963, 0.0138888888888889, 0.0277777777777778, 0.0462962962962963, 0.0694444444444444, 0.0972222222222222, 0.115740740740741, 0.125, 0.125, 0.115740740740741, 0.0972222222222222, 0.0694444444444444, 0.0462962962962963, 0.0277777777777778, 0.0138888888888889, 0.00462962962962963, 0.0, 0.0, 0.0]"
44
+ (1..21).collect { |x| Expectation.run(&roll_3d6_b).play(x) }.inspect.should == "[0.0, 0.0, 0.00462962962962963, 0.0138888888888889, 0.0277777777777778, 0.0462962962962963, 0.0694444444444444, 0.0833333333333333, 0.0902777777777778, 0.0902777777777777, 0.0833333333333333, 0.0694444444444444, 0.0625, 0.0601851851851852, 0.0578703703703704, 0.0555555555555556, 0.0532407407407407, 0.0462962962962963, 0.0354938271604938, 0.0239197530864197, 0.0146604938271605]"
45
+ end
46
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), %w(.. lib do_notation))
data/test/specs.rb ADDED
@@ -0,0 +1,66 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'do_notation/monads/array'
3
+
4
+ describe "Monad.run" do
5
+ specify "should have lexical scope" do
6
+ foo = "cousin"
7
+ bar = "removed"
8
+
9
+ array = Array.run do
10
+ x <- ["first", "second"]
11
+ y <- ["once", "twice"]
12
+
13
+ unit("#{x} #{foo} #{y} #{bar}")
14
+ end
15
+
16
+ array.should == ["first cousin once removed",
17
+ "first cousin twice removed",
18
+ "second cousin once removed",
19
+ "second cousin twice removed"]
20
+ end
21
+
22
+ specify "should be nestable" do
23
+ array = Array.run do
24
+ x <- run do
25
+ a <- ['A','a']
26
+ b <- ['B','b']
27
+
28
+ unit(a+b)
29
+ end
30
+
31
+ y <- run do
32
+ c <- ['C','c']
33
+ d <- ['D','d']
34
+
35
+ unit(c+d)
36
+ end
37
+
38
+ unit(x+y)
39
+ end
40
+
41
+ array.should == ["ABCD", "ABCd", "ABcD", "ABcd",
42
+ "AbCD", "AbCd", "AbcD", "Abcd",
43
+ "aBCD", "aBCd", "aBcD", "aBcd",
44
+ "abCD", "abCd", "abcD", "abcd"]
45
+ end
46
+ end
47
+
48
+ describe 'Monad#>>' do
49
+ specify "should compose two values, discarding the first" do
50
+ ([1] >> [2]).should == [2]
51
+ end
52
+ end
53
+
54
+ describe "Rewriter.pp" do
55
+ specify "should produce correct output" do
56
+ array = [:a, [:b],
57
+ [:c, :d,
58
+ :e]]
59
+
60
+ Rewriter.pp(array).should == <<CODE.strip
61
+ (:a (:b)
62
+ (:c :d
63
+ :e))
64
+ CODE
65
+ end
66
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: do_notation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Aanand Prasad
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-29 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ParseTree
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: ruby2ruby
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.9
34
+ version:
35
+ description: Haskell-style monad do-notation for Ruby
36
+ email: aanand.prasad@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ files:
44
+ - .gitignore
45
+ - Manifest
46
+ - README.rdoc
47
+ - Rakefile
48
+ - VERSION
49
+ - do-notation.gemspec
50
+ - lib/do_notation.rb
51
+ - lib/do_notation/monad.rb
52
+ - lib/do_notation/monad_plus.rb
53
+ - lib/do_notation/monads/array.rb
54
+ - lib/do_notation/monads/maybe.rb
55
+ - lib/do_notation/monads/simulations.rb
56
+ - lib/do_notation/rewriter.rb
57
+ - ruby-do-notation.gemspec
58
+ - test/array.rb
59
+ - test/maybe.rb
60
+ - test/monad_plus.rb
61
+ - test/simulations.rb
62
+ - test/spec_helper.rb
63
+ - test/specs.rb
64
+ has_rdoc: true
65
+ homepage: http://github.com/aanand/do_notation
66
+ licenses: []
67
+
68
+ post_install_message:
69
+ rdoc_options:
70
+ - --charset=UTF-8
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.3.4
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Haskell-style monad do-notation for Ruby
92
+ test_files:
93
+ - test/array.rb
94
+ - test/maybe.rb
95
+ - test/monad_plus.rb
96
+ - test/simulations.rb
97
+ - test/spec_helper.rb
98
+ - test/specs.rb