fubby 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ad6780eea6f05146816180477723f9863c9d861e
4
+ data.tar.gz: 8381795af6662e96c9a84fe3669ca5b53f70b371
5
+ SHA512:
6
+ metadata.gz: a458b1f8e734bce354a079dbafa4780231f9d0e5b1aae1897a61b0f36b4ee7292acd210f5e0ae7242f18a1fa81bdcd1ab366515d44d49763a26f2b2a8678cc37
7
+ data.tar.gz: 0a115ce3487eefcfcaca1c7492756c08399bea0d1d4697bd16d37d4f1f438ca4cdb0d4496f594b4b2d396bd35793dfb2989a9655c6608dfdc3efa7097b0e10bf
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ ansi (1.5.0)
5
+ builder (3.2.2)
6
+ minitest (5.8.4)
7
+ minitest-reporters (1.1.8)
8
+ ansi
9
+ builder
10
+ minitest (>= 5.0)
11
+ ruby-progressbar
12
+ ruby-progressbar (1.7.5)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ minitest
19
+ minitest-reporters
20
+
21
+ BUNDLED WITH
22
+ 1.11.2
@@ -0,0 +1,3 @@
1
+ # Fubby
2
+
3
+ Functional library for ruby
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.authors = ['JaredShay']
3
+ gem.email = ['jared.shay@gmail.com']
4
+ gem.description = %q{Functional library for ruby}
5
+ gem.summary = %q{Functional library for ruby}
6
+ gem.homepage = 'https://github.com/jaredshay/fubby'
7
+
8
+ gem.files = `git ls-files`.split("\n")
9
+ gem.test_files = `git ls-files -- test/*`.split("\n")
10
+ gem.name = 'fubby'
11
+ gem.require_paths = ['lib']
12
+ gem.version = '0.0.0'
13
+ gem.license = 'MIT'
14
+
15
+ gem.add_development_dependency 'miniest'
16
+ gem.add_development_dependency 'minitest-reporters'
17
+ end
@@ -0,0 +1,7 @@
1
+ require_relative './fubby/core'
2
+ require_relative './fubby/std_lib'
3
+
4
+ class F
5
+ extend Core
6
+ extend StdLib
7
+ end
@@ -0,0 +1,6 @@
1
+ module ArrayUtils
2
+ # concat :: [a] -> [a] -> [a]
3
+ def concat
4
+ ->(a1, a2) { a1 + a2 }
5
+ end
6
+ end
@@ -0,0 +1,62 @@
1
+ module Core
2
+ # identity :: a -> a
3
+ def identity
4
+ ->(x) { x }
5
+ end
6
+
7
+ # curry :: (a -> b) -> (a -> b)
8
+ def curry
9
+ _curry = ->(f, *given_args) {
10
+ ->(*remaining_args) {
11
+ total_args = given_args + remaining_args
12
+
13
+ total_args.length == f.arity ? f.(*total_args) : _curry.(f, *total_args)
14
+ }
15
+ }
16
+
17
+ ->(f) {
18
+ ->(*x) {
19
+ f.arity == x.length ? f.(*x) : _curry.(f, *x)
20
+ }
21
+ }
22
+ end
23
+
24
+ # reduce :: a, (b -> a), [b] -> a
25
+ def reduce
26
+ curry.(->(memo, f, array) {
27
+ if memo == nil
28
+ case array.length
29
+ when 0 then nil
30
+ when 1 then array[0]
31
+ else reduce.(f.(array[0], array[1]), f, array[2..-1])
32
+ end
33
+ else
34
+ case array.length
35
+ when 0 then memo
36
+ else reduce.(f.(memo, array[0]), f, array[1..-1])
37
+ end
38
+ end
39
+ })
40
+ end
41
+
42
+ # TODO: figure out how to notate many args. [f] isn't correct here.
43
+ # compose :: [f] -> (a -> b)
44
+ def compose
45
+ ->(*f) {
46
+ _compose = ->(x, *f) {
47
+ f.length == 1 ? f[0].(x) : f[0].(_compose.(x, *f[1..-1]))
48
+ }
49
+
50
+ ->(x) { _compose.(x, *f) }
51
+ }
52
+ end
53
+
54
+ # flip :: (a -> b) -> (a -> b)
55
+ def flip
56
+ ->(f) {
57
+ ->(*args) {
58
+ f.(*reverse.(args))
59
+ }
60
+ }
61
+ end
62
+ end
@@ -0,0 +1,113 @@
1
+ require_relative './core.rb'
2
+ require_relative './array_utils.rb'
3
+
4
+ module StdLib
5
+ C = Class.new { extend Core }
6
+ private_constant :C
7
+
8
+ A = Class.new { extend ArrayUtils }
9
+ private_constant :A
10
+
11
+ # length :: [a] -> Number
12
+ def length
13
+ ->(x) {
14
+ C.reduce.(0, ->(memo, _) { memo + 1 }, x)
15
+ }
16
+ end
17
+
18
+ # map :: (a -> b) -> [a] -> [b]
19
+ def map
20
+ C.curry.(
21
+ ->(f, x) {
22
+ fx = ->(memo, x) {
23
+ A.concat.(memo, [f.(x)])
24
+ }
25
+
26
+ C.reduce.([], fx, x)
27
+ }
28
+ )
29
+ end
30
+
31
+ # select :: (a -> Bool) -> [a] -> [a]
32
+ def select
33
+ C.curry.(
34
+ ->(f, x) {
35
+ fx = ->(memo, x) {
36
+ f.(x) == true ? A.concat.(memo, [x]) : memo
37
+ }
38
+
39
+ C.reduce.([], fx, x)
40
+ }
41
+ )
42
+ end
43
+
44
+ # reject :: (a -> Bool) -> [a] -> [a]
45
+ def reject
46
+ C.curry.(->(f, x) { x - select.(f, x) })
47
+ end
48
+
49
+ # any :: (a -> Bool) -> Bool
50
+ def any
51
+ C.curry.(
52
+ ->(f, x) {
53
+ fx = ->(memo, x) {
54
+ f.(x) ? true : memo
55
+ }
56
+
57
+ C.reduce.(fx, x, false)
58
+ }
59
+ )
60
+ end
61
+
62
+ # any :: (a -> Bool) -> Bool
63
+ def f_all
64
+ C.curry.(
65
+ ->(f, x) {
66
+ !any.(->(x) { x == false }, map.(f, x))
67
+ }
68
+ )
69
+ end
70
+
71
+ # add :: Int -> Int -> Int
72
+ def add
73
+ ->(x, y) { x + y }
74
+ end
75
+
76
+ # head :: [a] -> a
77
+ def head
78
+ ->(x) { x[0] }
79
+ end
80
+
81
+ # reverse :: [a] -> [a]
82
+ def reverse
83
+ ->(array) {
84
+ if array.empty? || length.(array) == 1
85
+ array
86
+ else
87
+ add.(reverse.(array[1..-1]), array[0])
88
+ end
89
+ }
90
+ end
91
+
92
+ # tail :: [a] -> a
93
+ def tail
94
+ C.compose.(head, reverse)
95
+ end
96
+
97
+ # TODO: figure out how to handle Strings and Chars
98
+ def str_head
99
+ ->(x) { x[0] }
100
+ end
101
+
102
+ # TODO implement this without `downcase`
103
+ # downcase :: String -> String
104
+ def downcase
105
+ ->(x) { x.downcase }
106
+ end
107
+
108
+ # TODO implement this without `capitalize`
109
+ # downcase :: String -> String
110
+ def upcase
111
+ ->(x) { x.capitalize }
112
+ end
113
+ end
@@ -0,0 +1,4 @@
1
+ require "minitest/autorun"
2
+ require "minitest/reporters"
3
+
4
+ Minitest::Reporters.use!(Minitest::Reporters::DefaultReporter.new)
@@ -0,0 +1,130 @@
1
+ require_relative '../test_helper.rb'
2
+ require_relative '../../lib/fubby/core.rb'
3
+
4
+ class T
5
+ extend Core
6
+ end
7
+
8
+ module Test
9
+ class IdentityTest < MiniTest::Test
10
+ def test_success
11
+ assert_equal 'x', T.identity.('x')
12
+ end
13
+
14
+ def test_fail
15
+ assert 'x' != T.identity.('y')
16
+ end
17
+ end
18
+
19
+ class CurryTest < MiniTest::Test
20
+ def test_defining_a_method_with_no_args
21
+ f = T.curry.(-> { 'x' })
22
+
23
+ assert_equal 'x', f.()
24
+ end
25
+
26
+ def test_defining_a_method_with_one_argument
27
+ f = T.curry.(->(x) { x })
28
+
29
+ assert_equal 'x', f.('x')
30
+ assert_equal 'x', f.().('x')
31
+ assert_equal 'x', f.().().('x')
32
+ end
33
+
34
+ def test_defining_a_method_with_two_arguments
35
+ f = T.curry.(->(x, y) { x + y })
36
+
37
+ assert_equal 3, f.(1, 2)
38
+ assert_equal 3, f.().(1, 2)
39
+ assert_equal 3, f.().().(1, 2)
40
+ assert_equal 3, f.(1).(2)
41
+ assert_equal 3, f.().(1).(2)
42
+ assert_equal 3, f.(1).().(2)
43
+ assert_equal 3, f.(1).().().(2)
44
+ assert_equal 3, f.().(1).().(2)
45
+ assert_equal 3, f.().(1).().().(2)
46
+ end
47
+
48
+ def test_defining_a_method_with_three_arguments
49
+ f = T.curry.(->(x, y, z) { x + y + z })
50
+
51
+ assert_equal 6, f.(1, 2, 3)
52
+ assert_equal 6, f.().(1, 2, 3)
53
+ assert_equal 6, f.().().(1, 2, 3)
54
+ assert_equal 6, f.(1, 2).(3)
55
+ assert_equal 6, f.().(1, 2).(3)
56
+ assert_equal 6, f.().(1, 2).().(3)
57
+ assert_equal 6, f.(1, 2).().(3)
58
+ assert_equal 6, f.(1).(2, 3)
59
+ assert_equal 6, f.().(1).(2, 3)
60
+ assert_equal 6, f.().(1).().(2, 3)
61
+ assert_equal 6, f.(1).(2).(3)
62
+ assert_equal 6, f.().(1).(2).(3)
63
+ assert_equal 6, f.().(1).().(2).(3)
64
+ assert_equal 6, f.().(1).().(2).().(3)
65
+ assert_equal 6, f.(1).().(2).(3)
66
+ assert_equal 6, f.(1).().(2).().(3)
67
+ assert_equal 6, f.(1).(2).().(3)
68
+ end
69
+ end
70
+
71
+ class ReduceTest < MiniTest::Test
72
+ def test_reducing_a_zero_element_array_with_no_memo
73
+ assert_equal nil, T.reduce.(nil, ->(x, y) { x + y }, [])
74
+ end
75
+
76
+ def test_reducing_a_zero_element_array_with_a_memo
77
+ assert_equal 'memo', T.reduce.('memo', ->(x, y) { x + y }, [])
78
+ end
79
+
80
+ def test_reducing_a_one_element_array_with_no_memo
81
+ assert_equal 1, T.reduce.(nil, ->(x, y) { x + y }, [1])
82
+ end
83
+
84
+ def test_reducing_a_one_element_array_with_a_memo
85
+ assert_equal 2, T.reduce.(1, ->(x, y) { x + y }, [1])
86
+ end
87
+
88
+ def test_reducing_a_two_element_array_with_no_memo
89
+ assert_equal 3, T.reduce.(nil, ->(x, y) { x + y }, [1, 2])
90
+ end
91
+
92
+ def test_reducing_a_two_element_array_with_a_memo
93
+ assert_equal 6, T.reduce.(1, ->(x, y) { x + y }, [2, 3])
94
+ end
95
+
96
+ def test_reducing_a_three_element_array_with_no_memo
97
+ assert_equal 6, T.reduce.(nil, ->(x, y) { x + y }, [1, 2, 3])
98
+ end
99
+
100
+ def test_reducing_a_three_element_array_with_a_memo
101
+ assert_equal 10, T.reduce.(1, ->(x, y) { x + y }, [2, 3, 4])
102
+ end
103
+
104
+ def test_currying
105
+ sum = T.reduce.(nil, ->(x, y) { x + y })
106
+
107
+ assert_equal 6, sum.([1, 2, 3])
108
+ end
109
+ end
110
+
111
+ class ComposeTest < MiniTest::Test
112
+ def test_composing_a_single_function
113
+ f = T.compose.(->(x) { x })
114
+
115
+ assert_equal 'x', f.('x')
116
+ end
117
+
118
+ def test_composing_two_functions
119
+ f = T.compose.(->(x) { x + 1 }, ->(x) { x * 2 })
120
+
121
+ assert_equal 5, f.(2)
122
+ end
123
+
124
+ def test_composing_three_functions
125
+ f = T.compose.(->(x) { x + 1 }, ->(x) { x * 2 }, ->(x) { x + 3 })
126
+
127
+ assert_equal 11, f.(2)
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,46 @@
1
+ require_relative '../test_helper.rb'
2
+ require_relative '../../lib/fubby/std_lib.rb'
3
+
4
+ class T
5
+ extend StdLib
6
+ end
7
+
8
+ class LengthTest < MiniTest::Test
9
+ def test_zero_length_array
10
+ assert_equal 0, T.length.([])
11
+ end
12
+
13
+ def test_array_with_one_element
14
+ assert_equal 1, T.length.([1])
15
+ end
16
+
17
+ def test_array_with_two_elements
18
+ assert_equal 2, T.length.(['a', 'b'])
19
+ end
20
+
21
+ def test_array_with_three_elements
22
+ assert_equal 3, T.length.([1, 2, 3])
23
+ end
24
+ end
25
+
26
+ class MapTest < MiniTest::Test
27
+ def test_zero_length_array
28
+ assert_equal [], T.map.(->(x) { x }, [])
29
+ end
30
+
31
+ def test_array_with_one_element
32
+ assert_equal [2], T.map.(->(x) { x + 1 }, [1])
33
+ end
34
+
35
+ def test_currying
36
+ double = T.map.(->(x) { x * 2 })
37
+
38
+ assert_equal [2, 4], double.([1, 2])
39
+ end
40
+ end
41
+
42
+ class SelectTest < MiniTest::Test
43
+ def test_zero_length_array
44
+ assert_equal [], T.select.(->(x) { x == 1 }, [])
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fubby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - JaredShay
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: miniest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest-reporters
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Functional library for ruby
42
+ email:
43
+ - jared.shay@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - Gemfile
49
+ - Gemfile.lock
50
+ - README.md
51
+ - fubby.gemspec
52
+ - lib/fubby.rb
53
+ - lib/fubby/array_utils.rb
54
+ - lib/fubby/core.rb
55
+ - lib/fubby/std_lib.rb
56
+ - test/test_helper.rb
57
+ - test/unit/core_test.rb
58
+ - test/unit/std_lib_test.rb
59
+ homepage: https://github.com/jaredshay/fubby
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.5.1
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Functional library for ruby
83
+ test_files:
84
+ - test/test_helper.rb
85
+ - test/unit/core_test.rb
86
+ - test/unit/std_lib_test.rb