funkr 0.0.21 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1 @@
1
+ rvm: 1.9.2
data/Rakefile CHANGED
@@ -1,2 +1,11 @@
1
1
  require 'bundler'
2
+ require 'rake/testtask'
3
+
2
4
  Bundler::GemHelper.install_tasks
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'test'
8
+ end
9
+
10
+ desc "Run tests"
11
+ task :default => :test
data/funkr.gemspec CHANGED
@@ -18,4 +18,5 @@ Gem::Specification.new do |s|
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
+ s.add_development_dependency 'rake', '~> 0.9.2'
21
22
  end
data/lib/funkr/adt/adt.rb CHANGED
@@ -1,25 +1,30 @@
1
1
  require "funkr/adt/matcher"
2
2
 
3
3
  module Funkr
4
+
5
+ # Very rought Algebraic Data Types. A class inheriting from ADT can
6
+ # declare constructors with #adt
4
7
  class ADT
5
8
 
6
9
  def initialize(const, *data)
7
10
  @const, @data = const, data
8
11
  end
9
-
12
+
13
+ # Declare ADT constructors, for example :
14
+ # class Maybe < ADT; adt :just, :nothing; end
10
15
  def self.adt(*constructs)
11
16
  build_adt(constructs)
12
17
  build_matcher(constructs)
13
18
  end
14
19
 
15
- def self.match_method=(method)
16
- @match_method = method
17
- end
18
-
19
- self.match_method = :safe
20
-
21
20
  def self.matcher; @matcher; end
22
21
 
22
+ # Match your ADT against its constructors, for example :
23
+ # a = Maybe.just("hello")
24
+ # a.match do |on|
25
+ # on.just{|x| puts x}
26
+ # on.nothing{ }
27
+ # end
23
28
  def match
24
29
  m = self.class.matcher.new(normal_form)
25
30
  yield m
@@ -27,10 +32,10 @@ module Funkr
27
32
  end
28
33
 
29
34
  def to_s
30
- format("%s%s%s",
35
+ format("{%s%s%s}",
31
36
  @const,
32
37
  @data.any? ? " : " : "",
33
- @data.map(&:inspect).join(" ") )
38
+ @data.map(&:inspect).join(", ") )
34
39
  end
35
40
 
36
41
  private
@@ -1,4 +1,5 @@
1
1
  module Funkr
2
+ # Should not be used directly
2
3
  class Matcher
3
4
 
4
5
  def initialize(match)
@@ -3,3 +3,6 @@ require 'funkr/categories/applicative'
3
3
  require 'funkr/categories/alternative'
4
4
  require 'funkr/categories/monoid'
5
5
  require 'funkr/categories/monad'
6
+
7
+
8
+ # Categories describe types capabilities.
@@ -1,62 +1,71 @@
1
1
  require 'funkr/categories'
2
2
 
3
+ # Extends array (as list) capabilities
3
4
  class Array
4
-
5
+
5
6
  include Funkr::Categories
6
-
7
+
7
8
  class << self
8
9
  def unit(e); self.new([e]); end
9
10
  alias pure unit
10
11
  def mzero; self.new(); end
11
12
  end
12
-
13
+
13
14
  ### Categories
14
-
15
- # array est déjà un functor via map
16
- # include Functor
17
-
18
-
15
+
16
+ # Array is already a functor with its correct map implementation
17
+
18
+
19
+ # Array can be made an applicative functor, for example :
20
+ # f = Array.curry_lift_proc{|x,y| x + y}
21
+ # f.apply([0,4]).apply([5,7]) => [5, 7, 9, 11]
22
+ # f.apply([0,4]).apply([]) => []
19
23
  include Applicative
20
24
  extend Applicative::ClassMethods
21
-
25
+
22
26
  def apply(to)
23
27
  map do |f|
24
28
  to.map{ |t| f.call(t)}
25
29
  end.flatten(1)
26
30
  end
27
-
31
+
32
+ # Array is Alternative whith empty? being zero
28
33
  include Alternative
29
-
34
+
35
+ # [].or_else{[5]} => [5]
30
36
  def or_else(&block)
31
37
  if empty? then yield
32
38
  else self end
33
39
  end
34
-
35
-
40
+
41
+
42
+ # Array is a monoid with mplus = (+) and mzero = []
36
43
  include Monoid
37
44
  extend Monoid::ClassMethods
38
-
45
+
46
+ # [5].mplus([6]) => [5,6]
39
47
  def mplus(m_y)
40
48
  self + m_y
41
49
  end
42
-
43
-
50
+
51
+
52
+ # Array is also a monad
44
53
  include Monad
45
54
  extend Monad::ClassMethods
46
-
55
+
47
56
  def bind(&block)
48
57
  self.map(&block).flatten(1)
49
58
  end
50
-
59
+
51
60
  def self.box(value)
52
61
  if value.nil? then self.mzero
53
62
  else self.unit(value) end
54
63
  end
55
-
64
+
56
65
  def unbox()
57
66
  if self.empty? then nil
58
67
  else self.first end
59
68
  end
60
-
61
-
69
+
70
+
62
71
  end
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'funkr/categories'
3
+
4
+ # Extends Hash capabilities
5
+ class Hash
6
+
7
+ # maps function over hash values
8
+ def map_v # &block
9
+ h = Hash.new(self.default)
10
+ self.each{|k,v| h[k] = yield(v)}
11
+ return h
12
+ end
13
+
14
+ # maps function over hash keys
15
+ def map_k # &block
16
+ h = Hash.new(self.default)
17
+ self.each{|k,v| h[yield(k)] = v}
18
+ return h
19
+ end
20
+
21
+ # maps function over hash keys and values. Block should take
22
+ # 2 parameters, and should return a 2 elements array.
23
+ def map_kv # &block
24
+ h = Hash.new(self.default)
25
+ self.each do |k,v|
26
+ nk, nv = yield(k,v)
27
+ h[nk] = nv
28
+ end
29
+ return h
30
+ end
31
+
32
+ include Funkr::Categories
33
+
34
+ class << self
35
+ def mzero; self.new(); end
36
+ end
37
+
38
+ ### Categories
39
+
40
+ # Hash is a functor via map_v, but unfortunatly a dumb map method is
41
+ # already defined by the enumerable module, and is kept for
42
+ # compatibility
43
+
44
+
45
+ # Hash is a monoid if values type is a monoid
46
+ include Monoid
47
+ extend Monoid::ClassMethods
48
+
49
+ def mplus(m_y)
50
+ self.merge(m_y){|k, v1, v2| v1.mplus(v2)}
51
+ end
52
+
53
+ end
@@ -1,3 +1,4 @@
1
1
  require 'funkr/extensions/fixnum'
2
2
  require 'funkr/extensions/array'
3
3
  require 'funkr/extensions/enumerable'
4
+ require 'funkr/extensions/hash'
@@ -4,25 +4,32 @@ require 'funkr/categories'
4
4
  module Funkr
5
5
  module Types
6
6
  class Maybe < ADT
7
-
7
+
8
8
  include Funkr::Categories
9
-
9
+
10
10
  adt :just, :nothing
11
-
11
+
12
12
  ### Categories
13
-
13
+
14
14
  include Functor
15
-
15
+
16
16
  def map(&block)
17
17
  self.match do |on|
18
18
  on.just {|v| self.class.just(yield(v))}
19
19
  on.nothing { self }
20
20
  end
21
21
  end
22
-
22
+
23
+ # Maybe can be made an applicative functor, for example :
24
+ # f = Maybe.curry_lift_proc{|x,y| x + y}
25
+ # a = Maybe.just(3)
26
+ # b = Maybe.just(4)
27
+ # c = Maybe.nothing
28
+ # f.apply(a).apply(b) => Just 7
29
+ # f.apply(a).apply(c) => Nothing
23
30
  include Applicative
24
31
  extend Applicative::ClassMethods
25
-
32
+
26
33
  def apply(to)
27
34
  self.match do |f_on|
28
35
  f_on.just do |f|
@@ -34,20 +41,20 @@ module Funkr
34
41
  f_on.nothing { self }
35
42
  end
36
43
  end
37
-
44
+
38
45
  include Alternative
39
-
46
+
40
47
  def or_else(&block)
41
48
  self.match do |on|
42
49
  on.just {|v| self}
43
50
  on.nothing { yield }
44
51
  end
45
52
  end
46
-
47
-
53
+
54
+
48
55
  include Monoid
49
56
  extend Monoid::ClassMethods
50
-
57
+
51
58
  def mplus(m_y)
52
59
  self.match do |x_on|
53
60
  x_on.nothing { m_y }
@@ -59,18 +66,18 @@ module Funkr
59
66
  end
60
67
  end
61
68
  end
62
-
63
-
69
+
70
+
64
71
  include Monad
65
72
  extend Monad::ClassMethods
66
-
73
+
67
74
  def bind(&block)
68
75
  self.match do |on|
69
76
  on.just {|v| yield(v)}
70
77
  on.nothing {self}
71
78
  end
72
79
  end
73
-
80
+
74
81
  def unbox(default=nil)
75
82
  self.match do |on|
76
83
  on.just {|v| v }
@@ -83,7 +90,7 @@ module Funkr
83
90
  alias pure just
84
91
  alias mzero nothing
85
92
  end
86
-
93
+
87
94
  def self.box(value)
88
95
  if value.nil? then self.nothing
89
96
  else self.just(value) end
@@ -94,7 +101,7 @@ module Funkr
94
101
  # a list of all the Just values.
95
102
  def self.concat(maybes)
96
103
  maybes.inject([]) do |a, e|
97
- e.match do |on|
104
+ e.match do |on|
98
105
  on.just{|v| a + [v]}
99
106
  on.nothing{ a }
100
107
  end
@@ -62,20 +62,18 @@ module Funkr
62
62
 
63
63
  def to_s; @key_vals.to_s; end
64
64
 
65
- end
66
-
67
- private
65
+ private
68
66
 
69
- def rebuild_array
70
- self.replace(@key_vals.values)
71
- end
67
+ def rebuild_array
68
+ self.replace(@key_vals.values)
69
+ end
72
70
 
73
- def check_keys(keys)
74
- unless keys.all?{|k| @allowed_keys.include?(k)} then
71
+ def check_keys(keys)
72
+ unless keys.all?{|k| @allowed_keys.include?(k)} then
75
73
  raise "#{self.class.to_s} forbidden key in update"
74
+ end
76
75
  end
77
- end
78
-
79
76
 
77
+ end
80
78
  end
81
79
  end
data/lib/funkr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Funkr
2
- VERSION = "0.0.21"
2
+ VERSION = "0.0.22"
3
3
  end
data/lib/funkr.rb CHANGED
@@ -2,6 +2,7 @@ if RUBY_VERSION.split(".")[0..1] == ["1","8"] then
2
2
  require 'funkr/compat/1.8'
3
3
  end
4
4
 
5
+ # Funkr brings some common functional programming constructs to ruby
5
6
  module Funkr
6
- # constructs defined in submodules
7
+
7
8
  end
@@ -0,0 +1,17 @@
1
+ require 'test/unit'
2
+ require 'funkr/types/container'
3
+
4
+ class TestContainer < Test::Unit::TestCase
5
+ C = Funkr::Types::Container
6
+
7
+ def test_comparable
8
+ # assert_equal(C.new('foo'), C.new('foo'))
9
+ end
10
+
11
+ def test_container
12
+ c = C.new("Value")
13
+ assert_equal("Value", c.unbox)
14
+ assert_equal("eulaV", c.map(&:reverse).unbox)
15
+ end
16
+
17
+ end
@@ -0,0 +1,63 @@
1
+ require 'test/unit'
2
+ require 'funkr/extensions'
3
+
4
+ class TestExtensions < Test::Unit::TestCase
5
+
6
+ def test_array_full_lift
7
+ a = [1,2,3]
8
+ b = [10,20,30]
9
+ f = Array.full_lift_proc{|x,y| x + y}
10
+ assert_equal([11, 21, 31, 12, 22, 32, 13, 23, 33], f.call(a,b))
11
+ assert_equal([], f.call(a,[]))
12
+ end
13
+
14
+ def test_array_monad
15
+ a = [1,2,3]
16
+ b = [10,20,30]
17
+ assert_equal([11, 21, 31, 12, 22, 32, 13, 23, 33],
18
+ a.bind do |x|
19
+ b.bind do |y|
20
+ Array.unit(x + y)
21
+ end
22
+ end)
23
+ end
24
+
25
+ def test_span
26
+ assert_equal([[1, 2, 4], [5, 7, 5, 8, 2, 10]],
27
+ [1,2,4,5,7,5,8,2,10].span{|x| x < 5})
28
+ end
29
+
30
+ def test_group_seq_by
31
+ assert_equal([[1], [2, 4], [5, 7, 5], [8, 2, 10]],
32
+ [1,2,4,5,7,5,8,2,10].group_seq_by{|x| x % 2})
33
+ end
34
+
35
+ def test_groups_of
36
+ assert_equal([[1, 2, 4, 5], [7, 5, 8, 2], [10]],
37
+ [1,2,4,5,7,5,8,2,10].groups_of(4))
38
+ end
39
+
40
+ def test_sliding_groups_of
41
+ assert_equal([[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6],
42
+ [5, 6, 7], [6, 7, 8], [7, 8, 9], [8, 9, 10]],
43
+ (1..10).to_a.sliding_groups_of(3))
44
+ end
45
+
46
+ def test_seq_index
47
+ assert_equal(30, (0..100).to_a.seq_index([30,31,32]))
48
+ end
49
+
50
+ def test_diff_with
51
+ a = [ {:v => 1}, {:v => 2}, {:v => 3}, {:v => 2}, {:v => 3} ]
52
+ b = [ {:v => 2}, {:v => 3}, {:v => 4}, {:v => 3}, {:v => 4} ]
53
+ assert_equal([[{:v=>1}], [{:v=>2}, {:v=>3}], [{:v=>4}]],
54
+ a.diff_with(b){|x,y| x[:v] == y[:v]})
55
+ end
56
+
57
+ def test_make_uniq_by
58
+ a = [ {:v => 1}, {:v => 2}, {:v => 3}, {:v => 2}, {:v => 3}, {:v => 1} ]
59
+ assert_equal([{:v=>1}, {:v=>2}, {:v=>3}],
60
+ a.make_uniq_by{|x,y| x[:v] == y[:v]})
61
+ end
62
+
63
+ end
data/test/test_hash.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'test/unit'
2
+ require 'funkr/extensions/hash'
3
+
4
+ class TestHash < Test::Unit::TestCase
5
+
6
+ def test_map_v
7
+ assert_equal( {a: 2, b: 3},
8
+ {a: 1, b: 2}.map_v{|v| v + 1} )
9
+ h = Hash.new(:patate)
10
+ assert_equal( :patate, h.map_v{|x| x + 1}[:foo] )
11
+ end
12
+
13
+ end
@@ -0,0 +1,73 @@
1
+ require 'test/unit'
2
+ require 'funkr/types/maybe'
3
+ require 'funkr/extensions'
4
+
5
+ class TestMaybe < Test::Unit::TestCase
6
+
7
+ M = Funkr::Types::Maybe
8
+
9
+ def j(v)
10
+ M.just(v)
11
+ end
12
+
13
+ def n
14
+ M.nothing
15
+ end
16
+
17
+ def test_map
18
+ assert_equal(j(6), j(5).map{|v| v+1 })
19
+ assert_equal(n, j(5).map{|v| v+1})
20
+ end
21
+
22
+ def test_curry_lift
23
+ f = M.curry_lift_proc{|x,y| x + y}
24
+ assert_equal(j(8), f.apply(j(5)).apply(j(3)))
25
+ assert_equal(n, f.apply(j(5)).apply(n))
26
+ end
27
+
28
+ def test_or_else
29
+ assert_equal(j(10), n.or_else{j(10)})
30
+ assert_equal(j(4), j(4).or_else{j(2)})
31
+ # assert_nothing_raised(j(2).or_else{raise 'should not be raised'})
32
+ end
33
+
34
+ def test_full_lift
35
+ f = M.full_lift_proc{|x,y| x + y}
36
+ assert_equal(j(6), f.call(j(4),j(2)))
37
+ assert_equal(n, f.call(j(1),n))
38
+ end
39
+
40
+ def test_lift_with
41
+ assert_equal(j(7), M.lift_with(j(4),j(3)){|x,y| x + y})
42
+ end
43
+
44
+ def test_mconcat
45
+ assert_equal(j(60), M.mconcat([j(10), j(20), n, j(30)]))
46
+ end
47
+
48
+ def test_concat
49
+ assert_equal([10,20,30], M.concat([j(10), j(20), n, j(30)]))
50
+ end
51
+
52
+ def test_comparisons
53
+ assert_equal(j(0), j(5) <=> j(5))
54
+ assert_equal(j(-1), j(5) <=> j(7))
55
+ assert_equal(j(1), j(2) <=> j(1))
56
+ assert_equal(j(true), j(3) < j(7))
57
+ assert_equal(n, j(4) <=> n)
58
+ assert_equal(n, n <=> j(2))
59
+ end
60
+
61
+ def test_unbox
62
+ assert_equal(5, j(5).unbox)
63
+ assert_equal(5, j(5).unbox(2))
64
+ assert_equal(nil, n.unbox)
65
+ assert_equal(2, n.unbox(2))
66
+ end
67
+
68
+ def test_box
69
+ assert_equal(j(5), M.box(5))
70
+ assert_equal(n, M.box(nil))
71
+ end
72
+
73
+ end
@@ -0,0 +1,25 @@
1
+ require 'test/unit'
2
+ require 'funkr/types/simple_record'
3
+
4
+ class TestSimpleRecords < Test::Unit::TestCase
5
+
6
+ def test_simple_records
7
+ r = Funkr::Types::SimpleRecord.new(name: "Paul", age: 27, city: "Rennes")
8
+ name, age, city = r
9
+ assert_equal("Paul", name)
10
+ assert_equal(27, age)
11
+ assert_equal("Rennes", city)
12
+ name, age, city = r.with(age: 28, city: "Trouville")
13
+ assert_equal("Paul", name)
14
+ assert_equal(28, age)
15
+ assert_equal("Trouville", city)
16
+
17
+ r.name = "Paul R"
18
+ assert_equal("Paul R", r.name)
19
+
20
+ r.update!(name: "Paul")
21
+ n, _x, _y = r
22
+ assert_equal("Paul", n)
23
+ end
24
+
25
+ end
metadata CHANGED
@@ -1,34 +1,37 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: funkr
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 21
9
- version: 0.0.21
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.22
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Paul Rivier
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-09-29 00:00:00 +02:00
18
- default_executable:
19
- dependencies: []
20
-
21
- description: "[EXPERIMENTAL] Some functionnal constructs for ruby, like ADT, functors, monads"
22
- email:
12
+ date: 2011-10-14 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &15155260 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.2
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *15155260
25
+ description: ! '[EXPERIMENTAL] Some functionnal constructs for ruby, like ADT, functors,
26
+ monads'
27
+ email:
23
28
  - paul (dot) r (dot) ml (at) gmail (dot) com
24
29
  executables: []
25
-
26
30
  extensions: []
27
-
28
31
  extra_rdoc_files: []
29
-
30
- files:
32
+ files:
31
33
  - .gitignore
34
+ - .travis.yml
32
35
  - Gemfile
33
36
  - Rakefile
34
37
  - funkr.gemspec
@@ -46,44 +49,40 @@ files:
46
49
  - lib/funkr/extensions/array.rb
47
50
  - lib/funkr/extensions/enumerable.rb
48
51
  - lib/funkr/extensions/fixnum.rb
52
+ - lib/funkr/extensions/hash.rb
49
53
  - lib/funkr/types.rb
50
54
  - lib/funkr/types/container.rb
51
55
  - lib/funkr/types/failable.rb
52
56
  - lib/funkr/types/maybe.rb
53
57
  - lib/funkr/types/simple_record.rb
54
58
  - lib/funkr/version.rb
55
- - test/tests.rb
56
- has_rdoc: true
59
+ - test/test_container.rb
60
+ - test/test_extensions.rb
61
+ - test/test_hash.rb
62
+ - test/test_maybe.rb
63
+ - test/test_simple_records.rb
57
64
  homepage: http://github.com/paul-r-ml/funkr
58
65
  licenses: []
59
-
60
66
  post_install_message:
61
67
  rdoc_options: []
62
-
63
- require_paths:
68
+ require_paths:
64
69
  - lib
65
- required_ruby_version: !ruby/object:Gem::Requirement
70
+ required_ruby_version: !ruby/object:Gem::Requirement
66
71
  none: false
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- segments:
71
- - 0
72
- version: "0"
73
- required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
77
  none: false
75
- requirements:
76
- - - ">="
77
- - !ruby/object:Gem::Version
78
- segments:
79
- - 0
80
- version: "0"
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
81
82
  requirements: []
82
-
83
83
  rubyforge_project: funkr
84
- rubygems_version: 1.3.7
84
+ rubygems_version: 1.8.10
85
85
  signing_key:
86
86
  specification_version: 3
87
- summary: "[EXPERIMENTAL] Some functionnal constructs for ruby"
87
+ summary: ! '[EXPERIMENTAL] Some functionnal constructs for ruby'
88
88
  test_files: []
89
-
data/test/tests.rb DELETED
@@ -1,136 +0,0 @@
1
- $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
2
-
3
- require 'rubygems'
4
- require 'funkr'
5
- require 'funkr/types'
6
- require 'funkr/extensions'
7
-
8
- include Funkr::Types
9
-
10
- m = Maybe.just(5)
11
-
12
- puts "\n> All different ?"
13
- puts([1,2,3].all_different?)
14
- puts([1,2,2,3].all_different?)
15
-
16
- puts "\n> Maybe"
17
- puts(m.match do |on|
18
- on.nothing{ Maybe.nothing }
19
- on.just{|v| Maybe.just(v + 1) }
20
- end.to_s)
21
-
22
- puts(m.map{|v| v+1 })
23
-
24
-
25
- n = Maybe.nothing
26
-
27
- puts(n.match do |on|
28
- on.nothing{ Maybe.nothing }
29
- on.just{|v| Maybe.just(v + 1) }
30
- end.to_s)
31
-
32
-
33
- puts "\n> Curry lift"
34
- f = Maybe.curry_lift_proc{|x,y| x + y}
35
- puts f.apply(m).apply(m)
36
- puts f.apply(m).apply(n)
37
- puts f.apply(m).apply(n.or_else{Maybe.just(10)})
38
-
39
- puts "\n> Full lift"
40
- f = Maybe.full_lift_proc{|x,y| x + y}
41
- puts f.call(m,m)
42
- puts f.call(m,n)
43
-
44
- puts "\n> Lift with"
45
- puts Maybe.lift_with(m,m){|x,y| x + y}
46
-
47
- puts "\n> mconcat"
48
- puts Maybe.mconcat([Maybe.just(10),
49
- Maybe.just(20),
50
- Maybe.nothing,
51
- Maybe.just(30)])
52
-
53
- puts "\n> concat"
54
- puts Maybe.concat([ Maybe.just(10),
55
- Maybe.just(20),
56
- Maybe.nothing,
57
- Maybe.just(30) ]).inspect
58
-
59
- puts "\n> Comparisons"
60
- puts(m <=> m)
61
- puts(m <=> (m.map{|v| v+1}))
62
- puts(m < (m.map{|v| v+1}))
63
- puts(m <=> n)
64
-
65
- puts "\n> Boxing and unboxing"
66
- puts m.unbox.inspect
67
- puts n.unbox.inspect
68
- puts (Maybe.box(12)).unbox.inspect
69
- puts (Maybe.box(nil)).unbox.inspect
70
-
71
- puts "\n> Containers"
72
- c = Container.new("Value")
73
- puts c.unbox
74
- puts c.map(&:reverse)
75
-
76
- a = [1,2,3]
77
- b = [10,20,30]
78
-
79
- puts "\n> Array full lift"
80
- f = Array.full_lift_proc{|x,y| x + y}
81
- puts f.call(a,b).inspect
82
- puts f.call(a,[]).inspect
83
-
84
- puts "\n> Array monad"
85
- puts(a.bind do |x|
86
- b.bind do |y|
87
- Array.unit(x + y)
88
- end
89
- end.inspect)
90
-
91
-
92
- puts "\n> span"
93
- puts([1,2,4,5,7,5,8,2,10].span{|x| x < 5}.inspect)
94
-
95
- puts "\n> group_seq_by"
96
- puts([1,2,4,5,7,5,8,2,10].group_seq_by{|x| x % 2}.inspect)
97
-
98
- puts "\n> groups_of"
99
- puts([1,2,4,5,7,5,8,2,10].groups_of(4).inspect)
100
-
101
- puts "\n> sliding_groups_of"
102
- puts((1..10).to_a.sliding_groups_of(3).inspect)
103
-
104
- puts "\n> seq_index (30)"
105
- puts((0..100).to_a.seq_index([30,31,32]))
106
-
107
- puts "\n> diff_with"
108
- a = [ {:v => 1}, {:v => 2}, {:v => 3}, {:v => 2}, {:v => 3} ]
109
- b = [ {:v => 2}, {:v => 3}, {:v => 4}, {:v => 3}, {:v => 4} ]
110
- puts(a.diff_with(b){|x,y| x[:v] == y[:v]}.inspect)
111
-
112
- puts "\n> make_uniq_by"
113
- a = [ {:v => 1}, {:v => 2}, {:v => 3}, {:v => 2}, {:v => 3}, {:v => 1} ]
114
- puts(a.make_uniq_by{|x,y| x[:v] == y[:v]}.inspect)
115
-
116
-
117
- puts "\n> SimpleRecords"
118
- r = SimpleRecord.new(name: "Paul", age: 27, city: "Rennes")
119
- puts r.to_s
120
- name, age, city = r
121
- puts format("%s is %s and lives in %s", name, age, city)
122
- name, age, city = r.with(age: 28, city: "Trouville")
123
- puts format("%s is now %s and lives in %s", name, age, city)
124
- puts format("%s is back to %s and really lives in %s", r.name, r.age, r.city)
125
- r.name = "Paul R"
126
- puts r.to_s
127
- r.update!(name: "Paul")
128
- n, _x, _y = r
129
- puts n
130
-
131
- class Person < SimpleRecord; fields :name, :age, :city; end
132
- r = Person.new(name: "Paul", age: 27, city: "Rennes")
133
- puts r.to_s
134
- x = Person.new(name: "Paul", age: 27, city: "Rennes", genre: "Male") rescue "Forbidden"
135
- y = Person.new(name: "Paul", age: 27) rescue "Forbidden"
136
-