funkr 0.0.23 → 0.0.24
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/README +13 -0
- data/lib/funkr.rb +12 -2
- data/lib/funkr/adt/adt.rb +9 -6
- data/lib/funkr/adt/matcher.rb +36 -25
- data/lib/funkr/categories/alternative.rb +4 -0
- data/lib/funkr/categories/applicative.rb +11 -1
- data/lib/funkr/categories/functor.rb +6 -1
- data/lib/funkr/categories/monad.rb +15 -1
- data/lib/funkr/categories/monoid.rb +2 -1
- data/lib/funkr/types/maybe.rb +63 -20
- data/lib/funkr/types/simple_record.rb +24 -9
- data/lib/funkr/version.rb +1 -1
- data/test/test_maybe.rb +2 -1
- metadata +52 -30
data/README
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Funkr brings some common functional programming constructs to ruby.
|
|
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}.
|
|
6
|
+
|
|
7
|
+
It also provide modules for common categories (Monoid, Monad,
|
|
8
|
+
Functor, Applicative ...), and extends common types to support
|
|
9
|
+
categories they belongs to (Array, Hash ...). Categories can also be
|
|
10
|
+
used with custom types, {Funkr::Types see provided classes}.
|
|
11
|
+
|
|
12
|
+
To get started, we recommand you to read the tests, and get feets wet
|
|
13
|
+
with provided Algebraic Data Types (like Maybe).
|
data/lib/funkr.rb
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
if RUBY_VERSION.split(".")[0..1] == ["1","8"] then
|
|
2
3
|
require 'funkr/compat/1.8'
|
|
3
4
|
end
|
|
4
5
|
|
|
5
|
-
# Funkr brings some common functional programming constructs to ruby
|
|
6
|
+
# Funkr brings some common functional programming constructs to ruby.
|
|
7
|
+
#
|
|
8
|
+
# In particular, it offers a simple mechanism to create Algebraïc Data
|
|
9
|
+
# Types and do pattern matching on them. For an exemple
|
|
10
|
+
# implementation, {Funkr::Types see provided classes}.
|
|
11
|
+
#
|
|
12
|
+
# It also provide modules for common categories (Monoid, Monad,
|
|
13
|
+
# Functor, Applicative ...), and extends common types to support
|
|
14
|
+
# categories they belongs to (Array, Hash ...). Categories can also be
|
|
15
|
+
# used with custom types, {Funkr::Types see provided classes}.
|
|
6
16
|
module Funkr
|
|
7
|
-
|
|
17
|
+
|
|
8
18
|
end
|
data/lib/funkr/adt/adt.rb
CHANGED
|
@@ -6,6 +6,8 @@ module Funkr
|
|
|
6
6
|
# declare constructors with #adt
|
|
7
7
|
class ADT
|
|
8
8
|
|
|
9
|
+
MATCHER = Funkr::Matchers::SafeMatcher
|
|
10
|
+
|
|
9
11
|
def initialize(const, *data)
|
|
10
12
|
@const, @data = const, data
|
|
11
13
|
end
|
|
@@ -25,12 +27,13 @@ module Funkr
|
|
|
25
27
|
# on.just{|x| puts x}
|
|
26
28
|
# on.nothing{ }
|
|
27
29
|
# end
|
|
28
|
-
def match
|
|
29
|
-
|
|
30
|
-
yield m
|
|
31
|
-
m.run_match
|
|
30
|
+
def match(&block)
|
|
31
|
+
self.class.matcher.match_with(normal_form, &block)
|
|
32
32
|
end
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
def unsafe_const; @const; end
|
|
35
|
+
def unsafe_data; @data; end
|
|
36
|
+
|
|
34
37
|
def to_s
|
|
35
38
|
format("{%s%s%s}",
|
|
36
39
|
@const,
|
|
@@ -56,7 +59,7 @@ module Funkr
|
|
|
56
59
|
end
|
|
57
60
|
|
|
58
61
|
def self.build_matcher(constructs)
|
|
59
|
-
@matcher = Class.new(
|
|
62
|
+
@matcher = Class.new(MATCHER) do
|
|
60
63
|
build_matchers(constructs)
|
|
61
64
|
end
|
|
62
65
|
end
|
data/lib/funkr/adt/matcher.rb
CHANGED
|
@@ -1,34 +1,45 @@
|
|
|
1
1
|
module Funkr
|
|
2
|
+
|
|
2
3
|
# Should not be used directly
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
constructs
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@
|
|
4
|
+
module Matchers
|
|
5
|
+
|
|
6
|
+
class SafeMatcher
|
|
7
|
+
|
|
8
|
+
def initialize(match)
|
|
9
|
+
@const, *@data = match
|
|
10
|
+
@runner = nil
|
|
11
|
+
@undefined = self.class.constructs.clone
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.build_matchers(constructs)
|
|
15
|
+
@constructs = constructs
|
|
16
|
+
constructs.each do |c|
|
|
17
|
+
name, *data = c
|
|
18
|
+
define_method(name) do |&b|
|
|
19
|
+
@undefined.delete(name)
|
|
20
|
+
if @const == name then
|
|
21
|
+
@runner = b
|
|
22
|
+
end
|
|
19
23
|
end
|
|
20
24
|
end
|
|
21
25
|
end
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
|
|
27
|
+
def self.constructs; @constructs; end
|
|
28
|
+
|
|
29
|
+
def self.match_with(normal_form) # &block
|
|
30
|
+
m = self.new(normal_form)
|
|
31
|
+
yield m
|
|
32
|
+
m.run_match
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def run_match
|
|
36
|
+
if @undefined.any? then
|
|
37
|
+
raise "Incomplete match, missing : #{@undefined.join(" ")}"
|
|
38
|
+
end
|
|
39
|
+
@runner.call(*@data)
|
|
29
40
|
end
|
|
30
|
-
|
|
41
|
+
|
|
31
42
|
end
|
|
32
|
-
|
|
43
|
+
|
|
33
44
|
end
|
|
34
45
|
end
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
module Funkr
|
|
2
2
|
module Categories
|
|
3
|
+
|
|
4
|
+
# Functors for which alternative (OR) behaviour can be defined
|
|
3
5
|
module Alternative
|
|
4
6
|
|
|
7
|
+
# Provide an alternative. The type must be as follow :
|
|
8
|
+
# Functor(A).or_else{ Functor(A) } : Functor(A)
|
|
5
9
|
def or_else
|
|
6
10
|
raise "Alternative#or_else not implemented"
|
|
7
11
|
end
|
|
@@ -1,16 +1,25 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
module Funkr
|
|
2
3
|
module Categories
|
|
4
|
+
|
|
5
|
+
# Functors that can contain a function and be applied to functors
|
|
6
|
+
# containing parameters for the function
|
|
3
7
|
module Applicative
|
|
4
|
-
|
|
8
|
+
|
|
9
|
+
# Apply the function living inside the functor . The type must be as follow :
|
|
10
|
+
# Functor(λ(A) : B).apply(Functor(A)) : Functor(B)
|
|
5
11
|
def apply
|
|
6
12
|
raise "Applicative#apply not implemented"
|
|
7
13
|
end
|
|
8
14
|
|
|
9
15
|
module ClassMethods
|
|
16
|
+
# Curryfy the lambda block, and lift it into the functor
|
|
10
17
|
def curry_lift_proc(&block)
|
|
11
18
|
self.pure(block.curry)
|
|
12
19
|
end
|
|
13
20
|
|
|
21
|
+
# Curryfy the lambda block over N parameter, lifting it to
|
|
22
|
+
# a lambda over N functors
|
|
14
23
|
def full_lift_proc(&block)
|
|
15
24
|
lambda do |*args|
|
|
16
25
|
args.inject(curry_lift_proc(&block)) do |a,e|
|
|
@@ -19,6 +28,7 @@ module Funkr
|
|
|
19
28
|
end
|
|
20
29
|
end
|
|
21
30
|
|
|
31
|
+
# Lift the block and call parameters on it.
|
|
22
32
|
def lift_with(*args, &block)
|
|
23
33
|
full_lift_proc(&block).call(*args)
|
|
24
34
|
end
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
module Funkr
|
|
2
3
|
module Categories
|
|
4
|
+
|
|
5
|
+
# A functor is a container that can be mapped over
|
|
3
6
|
module Functor
|
|
4
|
-
|
|
7
|
+
|
|
8
|
+
# Map over the constructor. The type must be as follow :
|
|
9
|
+
# Functor(A).map{|A| λ(A) : B} : Functor(B)
|
|
5
10
|
def map
|
|
6
11
|
raise "Functor#map not implemented"
|
|
7
12
|
end
|
|
@@ -1,7 +1,21 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
module Funkr
|
|
2
3
|
module Categories
|
|
4
|
+
|
|
5
|
+
# A functor can also be made an instance of Monad if you can
|
|
6
|
+
# define a bind operation on it. The bind operation must follow
|
|
7
|
+
# the monads laws :
|
|
8
|
+
# - Functor.unit(x).bind(f) == f.call(X)
|
|
9
|
+
# - monad.bind{|x| Functor.unit(x)} == monad
|
|
10
|
+
# - monad.bind{|x| f(monad).bind(g)} == monad.bind{|x| f(x)}.bind{|x| g(x)}
|
|
11
|
+
#
|
|
12
|
+
# Usually you will want your type to be a monad if you need to
|
|
13
|
+
# chain functions returning your type, and want to implement
|
|
14
|
+
# chaining logic once and for all (in bind).
|
|
3
15
|
module Monad
|
|
4
|
-
|
|
16
|
+
|
|
17
|
+
# Bind operation on monads. The type must be as follow :
|
|
18
|
+
# Monad(A).bind{|A| λ(A) : Monad(B)} : Monad(B)
|
|
5
19
|
def bind(&block)
|
|
6
20
|
raise "Monad#bind not implemented"
|
|
7
21
|
end
|
data/lib/funkr/types/maybe.rb
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
require 'funkr/adt/adt'
|
|
2
3
|
require 'funkr/categories'
|
|
3
4
|
|
|
4
5
|
module Funkr
|
|
5
6
|
module Types
|
|
7
|
+
|
|
8
|
+
# Algebraïc Data Type representing the possibility of a missing
|
|
9
|
+
# value : nothing. It cleanly replace the 'nil' paradigm often
|
|
10
|
+
# found in ruby code, and often leading to bugs. The Maybe type
|
|
11
|
+
# belongs to multiple categories, making it extremly expressive to
|
|
12
|
+
# use (functor, applicative, alternative, monad, monoid ... !).
|
|
13
|
+
#
|
|
14
|
+
# You will get maximum performance and maximum expressiveness if
|
|
15
|
+
# you can use provided high level functions (map, apply, or_else,
|
|
16
|
+
# ...) instead of pattern-matching yourself.
|
|
6
17
|
class Maybe < ADT
|
|
7
18
|
|
|
8
19
|
include Funkr::Categories
|
|
@@ -13,13 +24,24 @@ module Funkr
|
|
|
13
24
|
|
|
14
25
|
include Functor
|
|
15
26
|
|
|
27
|
+
# Maybe.nothing.map{|x| something(x)} # => nothing
|
|
28
|
+
# Maybe.just(x).map{|x| something(x)} # => just something(x)
|
|
29
|
+
#
|
|
30
|
+
# {Funkr::Categories::Functor#map see functor map}
|
|
16
31
|
def map(&block)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
32
|
+
# This implementation isn't safe but is a bit faster than the
|
|
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
|
|
38
|
+
if self.just? then self.class.just(yield(unsafe_content))
|
|
39
|
+
else self end
|
|
21
40
|
end
|
|
22
41
|
|
|
42
|
+
include Applicative
|
|
43
|
+
extend Applicative::ClassMethods
|
|
44
|
+
|
|
23
45
|
# Maybe can be made an applicative functor, for example :
|
|
24
46
|
# f = Maybe.curry_lift_proc{|x,y| x + y}
|
|
25
47
|
# a = Maybe.just(3)
|
|
@@ -27,23 +49,28 @@ module Funkr
|
|
|
27
49
|
# c = Maybe.nothing
|
|
28
50
|
# f.apply(a).apply(b) => Just 7
|
|
29
51
|
# f.apply(a).apply(c) => Nothing
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
52
|
+
#
|
|
53
|
+
# {Funkr::Categories::Applicative#apply see applicative apply}
|
|
33
54
|
def apply(to)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
end
|
|
55
|
+
# This implementation isn't safe but is a bit faster than the
|
|
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 }
|
|
62
|
+
# end
|
|
63
|
+
# end
|
|
64
|
+
# f_on.nothing { self }
|
|
65
|
+
# end
|
|
66
|
+
if self.just? and to.just? then
|
|
67
|
+
self.class.unit(self.unsafe_content.call(to.unsafe_content))
|
|
68
|
+
else self.class.nothing end
|
|
43
69
|
end
|
|
44
70
|
|
|
45
71
|
include Alternative
|
|
46
72
|
|
|
73
|
+
# {Funkr::Categories::Alternative#or_else see alternative or_else}
|
|
47
74
|
def or_else(&block)
|
|
48
75
|
self.match do |on|
|
|
49
76
|
on.just {|v| self}
|
|
@@ -55,6 +82,7 @@ module Funkr
|
|
|
55
82
|
include Monoid
|
|
56
83
|
extend Monoid::ClassMethods
|
|
57
84
|
|
|
85
|
+
# {Funkr::Categories::Monoid#mplus see monoid mplus}
|
|
58
86
|
def mplus(m_y)
|
|
59
87
|
self.match do |x_on|
|
|
60
88
|
x_on.nothing { m_y }
|
|
@@ -71,13 +99,24 @@ module Funkr
|
|
|
71
99
|
include Monad
|
|
72
100
|
extend Monad::ClassMethods
|
|
73
101
|
|
|
102
|
+
# {Funkr::Categories::Monad#bind see monad bind}
|
|
74
103
|
def bind(&block)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
104
|
+
# This implementation isn't safe but is a bit faster than the
|
|
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
|
|
110
|
+
if self.just? then yield(self.unsafe_content)
|
|
111
|
+
else self end
|
|
79
112
|
end
|
|
80
113
|
|
|
114
|
+
# Unbox a maybe value. You must provide a default in case of
|
|
115
|
+
# nothing. This method is not as safe as the others, as it will
|
|
116
|
+
# escape the content from the Maybe type safety.
|
|
117
|
+
#
|
|
118
|
+
# Maybe.just(5).unbox(:foobar) # => 5
|
|
119
|
+
# Maybe.nothing.unbox(:foobar) # => :foobar
|
|
81
120
|
def unbox(default=nil)
|
|
82
121
|
self.match do |on|
|
|
83
122
|
on.just {|v| v }
|
|
@@ -91,6 +130,10 @@ module Funkr
|
|
|
91
130
|
alias mzero nothing
|
|
92
131
|
end
|
|
93
132
|
|
|
133
|
+
# unsafe access to content, for performance purpose only
|
|
134
|
+
def unsafe_content; self.unsafe_data.first; end
|
|
135
|
+
|
|
136
|
+
# Box nil as nothing, and the rest as just x
|
|
94
137
|
def self.box(value)
|
|
95
138
|
if value.nil? then self.nothing
|
|
96
139
|
else self.just(value) end
|
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
module Funkr
|
|
3
3
|
module Types
|
|
4
|
-
|
|
5
|
-
class SimpleRecord < Array
|
|
6
|
-
### usage : r = SimpleRecord.new(Hash), then r.field
|
|
7
|
-
### r = SimpleRecord.new( name: "Paul", age: 27 )
|
|
8
|
-
### r.name => "Paul" ; r.age => 27
|
|
9
|
-
### name, age = r
|
|
10
4
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
# Simple records are a simple way to create records with named AND
|
|
6
|
+
# positional fields. Records can be updated on a per-field basis
|
|
7
|
+
# and pattern-matched as arrays. SimpleRecord has the following
|
|
8
|
+
# advantages above plain Hash :
|
|
9
|
+
#
|
|
10
|
+
# - fields are strict, you can't update an unexisting field by
|
|
11
|
+
# mistyping it or by combining it with a different structure
|
|
12
|
+
# - you have easy access to fields : named AND positional
|
|
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 ]
|
|
20
|
+
#
|
|
21
|
+
# other usage :
|
|
22
|
+
# class Person < SimpleRecord; fields :name, :age; end
|
|
23
|
+
# Person.new( name: Paul ) => Error, missing :age
|
|
24
|
+
class SimpleRecord < Array
|
|
14
25
|
|
|
15
26
|
class << self; attr_accessor :fields_list; end
|
|
16
27
|
@fields_list = nil
|
|
@@ -25,6 +36,8 @@ module Funkr
|
|
|
25
36
|
end
|
|
26
37
|
end
|
|
27
38
|
|
|
39
|
+
# Create a new SimpleRecord. Pass a Hash of keys and associated
|
|
40
|
+
# values if you want an inline record.
|
|
28
41
|
def initialize(key_vals)
|
|
29
42
|
fields = self.class.fields_list
|
|
30
43
|
if not fields.nil? then # record paramétré
|
|
@@ -46,11 +59,13 @@ module Funkr
|
|
|
46
59
|
end
|
|
47
60
|
end
|
|
48
61
|
|
|
62
|
+
# Update a simple record non-destructively
|
|
49
63
|
def with(new_key_vals)
|
|
50
64
|
check_keys(new_key_vals.keys)
|
|
51
65
|
self.class.new(@key_vals.merge(new_key_vals))
|
|
52
66
|
end
|
|
53
67
|
|
|
68
|
+
# Update a simple record destructively !!
|
|
54
69
|
def update!(new_key_vals)
|
|
55
70
|
check_keys(new_key_vals.keys)
|
|
56
71
|
@key_vals.merge!(new_key_vals)
|
data/lib/funkr/version.rb
CHANGED
data/test/test_maybe.rb
CHANGED
|
@@ -28,7 +28,8 @@ class TestMaybe < Test::Unit::TestCase
|
|
|
28
28
|
def test_or_else
|
|
29
29
|
assert_equal(j(10), n.or_else{j(10)})
|
|
30
30
|
assert_equal(j(4), j(4).or_else{j(2)})
|
|
31
|
-
|
|
31
|
+
assert_nothing_raised{ j(5).or_else{raise 'should not be raised'} }
|
|
32
|
+
assert_raise(RuntimeError){ n.or_else{raise 'should not be raised'} }
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def test_full_lift
|
metadata
CHANGED
|
@@ -1,38 +1,51 @@
|
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: funkr
|
|
3
|
-
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
prerelease: false
|
|
5
|
+
segments:
|
|
6
|
+
- 0
|
|
7
|
+
- 0
|
|
8
|
+
- 24
|
|
9
|
+
version: 0.0.24
|
|
6
10
|
platform: ruby
|
|
7
|
-
authors:
|
|
11
|
+
authors:
|
|
8
12
|
- Paul Rivier
|
|
9
13
|
autorequire:
|
|
10
14
|
bindir: bin
|
|
11
15
|
cert_chain: []
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
|
|
17
|
+
date: 2011-12-06 00:00:00 +01:00
|
|
18
|
+
default_executable:
|
|
19
|
+
dependencies:
|
|
20
|
+
- !ruby/object:Gem::Dependency
|
|
15
21
|
name: rake
|
|
16
|
-
|
|
22
|
+
prerelease: false
|
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
17
24
|
none: false
|
|
18
|
-
requirements:
|
|
25
|
+
requirements:
|
|
19
26
|
- - ~>
|
|
20
|
-
- !ruby/object:Gem::Version
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
segments:
|
|
29
|
+
- 0
|
|
30
|
+
- 9
|
|
31
|
+
- 2
|
|
21
32
|
version: 0.9.2
|
|
22
33
|
type: :development
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
monads'
|
|
27
|
-
email:
|
|
34
|
+
version_requirements: *id001
|
|
35
|
+
description: "[EXPERIMENTAL] Some functionnal constructs for ruby, like ADT, functors, monads"
|
|
36
|
+
email:
|
|
28
37
|
- paul (dot) r (dot) ml (at) gmail (dot) com
|
|
29
38
|
executables: []
|
|
39
|
+
|
|
30
40
|
extensions: []
|
|
41
|
+
|
|
31
42
|
extra_rdoc_files: []
|
|
32
|
-
|
|
43
|
+
|
|
44
|
+
files:
|
|
33
45
|
- .gitignore
|
|
34
46
|
- .travis.yml
|
|
35
47
|
- Gemfile
|
|
48
|
+
- README
|
|
36
49
|
- Rakefile
|
|
37
50
|
- funkr.gemspec
|
|
38
51
|
- lib/funkr.rb
|
|
@@ -61,28 +74,37 @@ files:
|
|
|
61
74
|
- test/test_hash.rb
|
|
62
75
|
- test/test_maybe.rb
|
|
63
76
|
- test/test_simple_records.rb
|
|
77
|
+
has_rdoc: true
|
|
64
78
|
homepage: http://github.com/paul-r-ml/funkr
|
|
65
79
|
licenses: []
|
|
80
|
+
|
|
66
81
|
post_install_message:
|
|
67
82
|
rdoc_options: []
|
|
68
|
-
|
|
83
|
+
|
|
84
|
+
require_paths:
|
|
69
85
|
- lib
|
|
70
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
71
87
|
none: false
|
|
72
|
-
requirements:
|
|
73
|
-
- -
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
|
|
76
|
-
|
|
88
|
+
requirements:
|
|
89
|
+
- - ">="
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
segments:
|
|
92
|
+
- 0
|
|
93
|
+
version: "0"
|
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
95
|
none: false
|
|
78
|
-
requirements:
|
|
79
|
-
- -
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
segments:
|
|
100
|
+
- 0
|
|
101
|
+
version: "0"
|
|
82
102
|
requirements: []
|
|
103
|
+
|
|
83
104
|
rubyforge_project: funkr
|
|
84
|
-
rubygems_version: 1.
|
|
105
|
+
rubygems_version: 1.3.7
|
|
85
106
|
signing_key:
|
|
86
107
|
specification_version: 3
|
|
87
|
-
summary:
|
|
108
|
+
summary: "[EXPERIMENTAL] Some functionnal constructs for ruby"
|
|
88
109
|
test_files: []
|
|
110
|
+
|