funkr 0.0.21 → 0.0.22

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/.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
-