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.
- checksums.yaml +7 -0
- data/README +8 -5
- data/funkr.gemspec +22 -4
- data/lib/funkr/adt/adt.rb +6 -6
- data/lib/funkr/adt/matcher.rb +1 -1
- data/lib/funkr/extensions.rb +1 -1
- data/lib/funkr/extensions/array.rb +7 -4
- data/lib/funkr/extensions/enumerable.rb +7 -7
- data/lib/funkr/extensions/{fixnum.rb → integer.rb} +5 -2
- data/lib/funkr/types/maybe.rb +27 -27
- data/lib/funkr/types/simple_record.rb +9 -8
- data/lib/funkr/version.rb +1 -1
- data/test/test_extensions.rb +5 -0
- metadata +55 -58
checksums.yaml
ADDED
@@ -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
|
4
|
-
Types and do pattern matching on them. For an exemple
|
5
|
-
|
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,
|
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.
|
data/funkr.gemspec
CHANGED
@@ -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{
|
13
|
-
s.description =
|
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', '~>
|
39
|
+
s.add_development_dependency 'rake', '~> 12.3'
|
22
40
|
end
|
data/lib/funkr/adt/adt.rb
CHANGED
@@ -13,7 +13,7 @@ module Funkr
|
|
13
13
|
end
|
14
14
|
|
15
15
|
# Declare ADT constructors, for example :
|
16
|
-
#
|
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
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
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
|
data/lib/funkr/adt/matcher.rb
CHANGED
data/lib/funkr/extensions.rb
CHANGED
@@ -17,9 +17,10 @@ class Array
|
|
17
17
|
|
18
18
|
|
19
19
|
# Array can be made an applicative functor, for example :
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
62
|
-
#
|
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
|
-
#
|
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)
|
data/lib/funkr/types/maybe.rb
CHANGED
@@ -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
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
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
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
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
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
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 :
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
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
|
-
#
|
23
|
-
#
|
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
|
data/lib/funkr/version.rb
CHANGED
data/test/test_extensions.rb
CHANGED
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
|
-
|
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
|
-
|
18
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
45
|
-
- .
|
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
|
-
|
88
|
-
requirements:
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
89
93
|
- - ">="
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
-
|
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:
|
103
|
+
rubygems_version: 2.7.6.2
|
106
104
|
signing_key:
|
107
|
-
specification_version:
|
108
|
-
summary:
|
105
|
+
specification_version: 4
|
106
|
+
summary: Functionnal toolbox for Ruby
|
109
107
|
test_files: []
|
110
|
-
|