funkr 0.0.24 → 0.0.30

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7cb4f5366a7c1c68082cb5982e5cd7700440d94344fdfb8cdff7bd94b723bb4a
4
+ data.tar.gz: 4c79978d034dbbc0fc650644808ca3de77efa6e934770a4602d09ea042891c01
5
+ SHA512:
6
+ metadata.gz: e2767fe18dbf634574240a8b40acf5a8d42f2caa0770605a3b9b5e25ff62b9307552088da7a381f9c3a5e5ee3cb2b9dd2a6db93f7d8034b7ad6641d595cc5307
7
+ data.tar.gz: c7110ff660fb041f5f09b63bff32e187c99fccfec855d75d1be99993115f1654255144185140cdd1b47dffc4c78d3a8d2fac0e4d60fe9ab2ab120ef05726c6ed
data/README CHANGED
@@ -1,13 +1,16 @@
1
1
  Funkr brings some common functional programming constructs to ruby.
2
2
 
3
- In particular, it offers a simple mechanism to create Algebraïc Data
4
- Types and do pattern matching on them. For an exemple
5
- implementation, {Funkr::Types see provided classes}.
3
+ In particular, it offers a simple mechanism to create Algebraic Data
4
+ Types and do pattern matching on them. For an exemple implementation,
5
+ see provided classes.
6
6
 
7
7
  It also provide modules for common categories (Monoid, Monad,
8
8
  Functor, Applicative ...), and extends common types to support
9
9
  categories they belongs to (Array, Hash ...). Categories can also be
10
- used with custom types, {Funkr::Types see provided classes}.
10
+ used with custom types, see provided classes.
11
11
 
12
12
  To get started, we recommand you to read the tests, and get feets wet
13
- with provided Algebraic Data Types (like Maybe).
13
+ with provided Algebraic Data Types (like Maybe).
14
+
15
+ Funkr is heavily used by its authors in production at
16
+ http://www.atikteam.com/en to ensure better code reliability.
@@ -1,4 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
1
  $:.push File.expand_path("../lib", __FILE__)
3
2
  require "funkr/version"
4
3
 
@@ -9,8 +8,27 @@ Gem::Specification.new do |s|
9
8
  s.authors = ["Paul Rivier"]
10
9
  s.email = ["paul (dot) r (dot) ml (at) gmail (dot) com"]
11
10
  s.homepage = "http://github.com/paul-r-ml/funkr"
12
- s.summary = %q{[EXPERIMENTAL] Some functionnal constructs for ruby}
13
- s.description = %q{[EXPERIMENTAL] Some functionnal constructs for ruby, like ADT, functors, monads}
11
+ s.summary = %q{Functionnal toolbox for Ruby}
12
+ s.description = <<EOF
13
+ Funkr is a functionnal toolbox for the Ruby language.
14
+
15
+ In particular, it offers a simple mechanism to create Algebraic Data
16
+ Types and do pattern matching on them.
17
+
18
+ -
19
+
20
+ It also provide modules for common categories (Monoid, Monad,
21
+ Functor, Applicative ...), and extends common types to support
22
+ categories they belongs to (Array, Hash ...). Categories can also be
23
+ used with custom types, see provided classes.
24
+
25
+ -
26
+
27
+ Array and Hash classes are extended with methods providing correct
28
+ behaviour with respect to categories. Enumerable module comes with
29
+ a lot of useful functions for working with lists and sets. See the
30
+ module documentation and the test suite for examples.
31
+ EOF
14
32
 
15
33
  s.rubyforge_project = "funkr"
16
34
 
@@ -18,5 +36,5 @@ Gem::Specification.new do |s|
18
36
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
37
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
38
  s.require_paths = ["lib"]
21
- s.add_development_dependency 'rake', '~> 0.9.2'
39
+ s.add_development_dependency 'rake', '~> 12.3'
22
40
  end
@@ -13,7 +13,7 @@ module Funkr
13
13
  end
14
14
 
15
15
  # Declare ADT constructors, for example :
16
- # class Maybe < ADT; adt :just, :nothing; end
16
+ # class Maybe < ADT; adt :just, :nothing; end
17
17
  def self.adt(*constructs)
18
18
  build_adt(constructs)
19
19
  build_matcher(constructs)
@@ -22,11 +22,11 @@ module Funkr
22
22
  def self.matcher; @matcher; end
23
23
 
24
24
  # Match your ADT against its constructors, for example :
25
- # a = Maybe.just("hello")
26
- # a.match do |on|
27
- # on.just{|x| puts x}
28
- # on.nothing{ }
29
- # end
25
+ # a = Maybe.just("hello")
26
+ # a.match do |on|
27
+ # on.just{|x| puts x}
28
+ # on.nothing{ }
29
+ # end
30
30
  def match(&block)
31
31
  self.class.matcher.match_with(normal_form, &block)
32
32
  end
@@ -14,7 +14,7 @@ module Funkr
14
14
  def self.build_matchers(constructs)
15
15
  @constructs = constructs
16
16
  constructs.each do |c|
17
- name, *data = c
17
+ name, *_ = c
18
18
  define_method(name) do |&b|
19
19
  @undefined.delete(name)
20
20
  if @const == name then
@@ -1,4 +1,4 @@
1
- require 'funkr/extensions/fixnum'
1
+ require 'funkr/extensions/integer'
2
2
  require 'funkr/extensions/array'
3
3
  require 'funkr/extensions/enumerable'
4
4
  require 'funkr/extensions/hash'
@@ -17,9 +17,10 @@ class Array
17
17
 
18
18
 
19
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([]) => []
20
+ #
21
+ # f = Array.curry_lift_proc{|x,y| x + y}
22
+ # f.apply([0,4]).apply([5,7]) => [5, 7, 9, 11]
23
+ # f.apply([0,4]).apply([]) => []
23
24
  include Applicative
24
25
  extend Applicative::ClassMethods
25
26
 
@@ -49,10 +50,12 @@ class Array
49
50
  end
50
51
 
51
52
 
52
- # Array is also a monad
53
53
  include Monad
54
54
  extend Monad::ClassMethods
55
55
 
56
+ # Array is also a monad
57
+ #
58
+ # [1,2].bind{|x| [3,4].bind{|y| x + y}} # => [4,5,5,6]
56
59
  def bind(&block)
57
60
  self.map(&block).flatten(1)
58
61
  end
@@ -40,26 +40,27 @@ module Enumerable
40
40
  return [ inc, [] ]
41
41
  end
42
42
 
43
- # Constitue des groupes disjoints de n éléments au plus
43
+ # builds up disjoint groups of n elements or less
44
44
  def groups_of(n)
45
45
  g = self.take(n)
46
46
  return [] if g.empty?
47
47
  [g] + self.drop(n).groups_of(n)
48
48
  end
49
49
 
50
- # constitue des groupes de n éléments exactement, décalés de 1
50
+ # builds up sliding groups of exactly n elements
51
51
  def sliding_groups_of(n)
52
52
  return [] if self.size < n
53
53
  [ self.take(n) ] + self.drop(1).sliding_groups_of(n)
54
54
  end
55
55
 
56
- # trouve l'index d'une séquence
56
+ # find the position of a sequence
57
+ # [1,2,3,4,5,4,3,2,1].seq_index([4,3]) # => 5
57
58
  def seq_index(seq)
58
59
  self.sliding_groups_of(seq.size).index(seq)
59
60
  end
60
61
 
61
- # Prend un prédicat p(x,y), et construit un tableau dans lequel tous
62
- # les couples (a,b), tels que 'a' précède 'b', vérifient p(a,b).
62
+ # Takes a block predicate p(x,y) and builds an array of elements so
63
+ # that for any (a,b), a being before b in the list, p(a,b) holds.
63
64
  def make_uniq_by(&block)
64
65
  result = []
65
66
  self.each do |e|
@@ -68,8 +69,7 @@ module Enumerable
68
69
  return result
69
70
  end
70
71
 
71
- # difference entre 2 tableaux, retourne le triplet [ [missing] , [intersection], [added] ]
72
- # codé en impératif parce que inject est trop lent :(
72
+ # compare 2 enumerables, and returns [ [missing] , [intersection], [added] ]
73
73
  def diff_with(other, &block)
74
74
  m, i, a = [], [], []
75
75
  u_s = self.make_uniq_by(&block)
@@ -1,6 +1,6 @@
1
1
  require "funkr/categories/monoid"
2
2
 
3
- class Fixnum
3
+ class Integer
4
4
 
5
5
  include Funkr::Categories
6
6
 
@@ -10,6 +10,9 @@ class Fixnum
10
10
  def mplus(y)
11
11
  self + y
12
12
  end
13
+
14
+ def self.mzero
15
+ 0
16
+ end
13
17
 
14
18
  end
15
-
@@ -23,18 +23,18 @@ module Funkr
23
23
  ### Categories
24
24
 
25
25
  include Functor
26
-
27
- # Maybe.nothing.map{|x| something(x)} # => nothing
28
- # Maybe.just(x).map{|x| something(x)} # => just something(x)
29
- #
26
+
30
27
  # {Funkr::Categories::Functor#map see functor map}
28
+ #
29
+ # Maybe.nothing.map{|x| something(x)} # => nothing
30
+ # Maybe.just(x).map{|x| something(x)} # => just something(x)
31
31
  def map(&block)
32
32
  # This implementation isn't safe but is a bit faster than the
33
33
  # safe one. A safe implementation would be as follow :
34
- # self.match do |on|
35
- # on.just {|v| self.class.just(yield(v))}
36
- # on.nothing { self }
37
- # end
34
+ # self.match do |on|
35
+ # on.just {|v| self.class.just(yield(v))}
36
+ # on.nothing { self }
37
+ # end
38
38
  if self.just? then self.class.just(yield(unsafe_content))
39
39
  else self end
40
40
  end
@@ -42,27 +42,27 @@ module Funkr
42
42
  include Applicative
43
43
  extend Applicative::ClassMethods
44
44
 
45
- # Maybe can be made an applicative functor, for example :
46
- # f = Maybe.curry_lift_proc{|x,y| x + y}
47
- # a = Maybe.just(3)
48
- # b = Maybe.just(4)
49
- # c = Maybe.nothing
50
- # f.apply(a).apply(b) => Just 7
51
- # f.apply(a).apply(c) => Nothing
52
- #
53
45
  # {Funkr::Categories::Applicative#apply see applicative apply}
46
+ #
47
+ # Maybe can be made an applicative functor, for example :
48
+ # f = Maybe.curry_lift_proc{|x,y| x + y}
49
+ # a = Maybe.just(3)
50
+ # b = Maybe.just(4)
51
+ # c = Maybe.nothing
52
+ # f.apply(a).apply(b) => Just 7
53
+ # f.apply(a).apply(c) => Nothing
54
54
  def apply(to)
55
55
  # This implementation isn't safe but is a bit faster than the
56
56
  # safe one. A safe implementation would be as follow :
57
- # self.match do |f_on|
58
- # f_on.just do |f|
59
- # to.match do |t_on|
60
- # t_on.just {|t| self.class.unit(f.call(t)) }
61
- # t_on.nothing { to }
57
+ # self.match do |f_on|
58
+ # f_on.just do |f|
59
+ # to.match do |t_on|
60
+ # t_on.just {|t| self.class.unit(f.call(t)) }
61
+ # t_on.nothing { to }
62
+ # end
62
63
  # end
64
+ # f_on.nothing { self }
63
65
  # end
64
- # f_on.nothing { self }
65
- # end
66
66
  if self.just? and to.just? then
67
67
  self.class.unit(self.unsafe_content.call(to.unsafe_content))
68
68
  else self.class.nothing end
@@ -103,10 +103,10 @@ module Funkr
103
103
  def bind(&block)
104
104
  # This implementation isn't safe but is a bit faster than the
105
105
  # safe one. A safe implementation would be as follow :
106
- # self.match do |on|
107
- # on.just {|v| yield(v)}
108
- # on.nothing {self}
109
- # end
106
+ # self.match do |on|
107
+ # on.just {|v| yield(v)}
108
+ # on.nothing {self}
109
+ # end
110
110
  if self.just? then yield(self.unsafe_content)
111
111
  else self end
112
112
  end
@@ -11,16 +11,17 @@ module Funkr
11
11
  # mistyping it or by combining it with a different structure
12
12
  # - you have easy access to fields : named AND positional
13
13
  #
14
- # usage : r = SimpleRecord.new(Hash), then r.field
15
- # r = SimpleRecord.new( name: "Paul", age: 27 )
16
- # r.name # => "Paul"
17
- # r.age # => 27
18
- # name, age = r # => [ "Paul", 27 ]
19
- # r.with(age: 29) # => [ "Paul", 29 ]
14
+ # usage :
15
+ #
16
+ # r = SimpleRecord.new( name: "Paul", age: 27 )
17
+ # r.name # => "Paul"
18
+ # r.age # => 27
19
+ # name, age = r # => [ "Paul", 27 ]
20
+ # r.with(age: 29) # => [ "Paul", 29 ]
20
21
  #
21
22
  # other usage :
22
- # class Person < SimpleRecord; fields :name, :age; end
23
- # Person.new( name: Paul ) => Error, missing :age
23
+ # class Person < SimpleRecord; fields :name, :age; end
24
+ # Person.new( name: Paul ) => Error, missing :age
24
25
  class SimpleRecord < Array
25
26
 
26
27
  class << self; attr_accessor :fields_list; end
@@ -1,3 +1,3 @@
1
1
  module Funkr
2
- VERSION = "0.0.24"
2
+ VERSION = "0.0.30"
3
3
  end
@@ -66,4 +66,9 @@ class TestExtensions < Test::Unit::TestCase
66
66
  a.make_uniq_by{|x,y| x[:v] == y[:v]})
67
67
  end
68
68
 
69
+
70
+ def test_mconcat_integer
71
+ assert_equal(6, Integer.mconcat([1,2,3]))
72
+ end
73
+
69
74
  end
metadata CHANGED
@@ -1,49 +1,56 @@
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
- - 24
9
- version: 0.0.24
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.30
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Paul Rivier
13
8
  autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
-
17
- date: 2011-12-06 00:00:00 +01:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2020-11-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: rake
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ~>
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- - 9
31
- - 2
32
- version: 0.9.2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12.3'
33
20
  type: :development
34
- version_requirements: *id001
35
- description: "[EXPERIMENTAL] Some functionnal constructs for ruby, like ADT, functors, monads"
36
- email:
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '12.3'
27
+ description: |
28
+ Funkr is a functionnal toolbox for the Ruby language.
29
+
30
+ In particular, it offers a simple mechanism to create Algebraic Data
31
+ Types and do pattern matching on them.
32
+
33
+ -
34
+
35
+ It also provide modules for common categories (Monoid, Monad,
36
+ Functor, Applicative ...), and extends common types to support
37
+ categories they belongs to (Array, Hash ...). Categories can also be
38
+ used with custom types, see provided classes.
39
+
40
+ -
41
+
42
+ Array and Hash classes are extended with methods providing correct
43
+ behaviour with respect to categories. Enumerable module comes with
44
+ a lot of useful functions for working with lists and sets. See the
45
+ module documentation and the test suite for examples.
46
+ email:
37
47
  - paul (dot) r (dot) ml (at) gmail (dot) com
38
48
  executables: []
39
-
40
49
  extensions: []
41
-
42
50
  extra_rdoc_files: []
43
-
44
- files:
45
- - .gitignore
46
- - .travis.yml
51
+ files:
52
+ - ".gitignore"
53
+ - ".travis.yml"
47
54
  - Gemfile
48
55
  - README
49
56
  - Rakefile
@@ -61,8 +68,8 @@ files:
61
68
  - lib/funkr/extensions.rb
62
69
  - lib/funkr/extensions/array.rb
63
70
  - lib/funkr/extensions/enumerable.rb
64
- - lib/funkr/extensions/fixnum.rb
65
71
  - lib/funkr/extensions/hash.rb
72
+ - lib/funkr/extensions/integer.rb
66
73
  - lib/funkr/types.rb
67
74
  - lib/funkr/types/container.rb
68
75
  - lib/funkr/types/failable.rb
@@ -74,37 +81,27 @@ files:
74
81
  - test/test_hash.rb
75
82
  - test/test_maybe.rb
76
83
  - test/test_simple_records.rb
77
- has_rdoc: true
78
84
  homepage: http://github.com/paul-r-ml/funkr
79
85
  licenses: []
80
-
86
+ metadata: {}
81
87
  post_install_message:
82
88
  rdoc_options: []
83
-
84
- require_paths:
89
+ require_paths:
85
90
  - lib
86
- required_ruby_version: !ruby/object:Gem::Requirement
87
- none: false
88
- requirements:
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
89
93
  - - ">="
90
- - !ruby/object:Gem::Version
91
- segments:
92
- - 0
93
- version: "0"
94
- required_rubygems_version: !ruby/object:Gem::Requirement
95
- none: false
96
- requirements:
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
97
98
  - - ">="
98
- - !ruby/object:Gem::Version
99
- segments:
100
- - 0
101
- version: "0"
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
102
101
  requirements: []
103
-
104
102
  rubyforge_project: funkr
105
- rubygems_version: 1.3.7
103
+ rubygems_version: 2.7.6.2
106
104
  signing_key:
107
- specification_version: 3
108
- summary: "[EXPERIMENTAL] Some functionnal constructs for ruby"
105
+ specification_version: 4
106
+ summary: Functionnal toolbox for Ruby
109
107
  test_files: []
110
-