kleisli 0.1.0 → 0.2.0
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 +4 -4
- data/README.md +28 -1
- data/lib/kleisli/applicative_functor.rb +4 -0
- data/lib/kleisli/either.rb +8 -0
- data/lib/kleisli/maybe.rb +18 -0
- data/lib/kleisli/version.rb +1 -1
- data/test/kleisli/either_test.rb +12 -0
- data/test/kleisli/maybe_test.rb +12 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 997aca6d77f858cf9262df7edbc913179cd8004f
|
4
|
+
data.tar.gz: dac24d37b400e98703e6299fb6a702ea5df773eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 009f9357a66c1003610f90cd86e734c00632efa6b8b511d5eec2bdc91daceb41bc3f1ebf667615065aefd506435510f8de97a83518a2e6259241f649224d0fef
|
7
|
+
data.tar.gz: 77f136e1fb92e6d315c7b423aa2c5e8f32b3f3f1f2ec0071488c51557cab9d52d51a3d6b1f105211f2525979825456a4ea09ea53aa78d6e0b2809ffa581f9ec7
|
data/README.md
CHANGED
@@ -23,7 +23,10 @@ which for each monad below).
|
|
23
23
|
Kleisli uses a clever Ruby syntax trick to implement the `bind` operator, which
|
24
24
|
looks like this: `>->` when used with a block. We will probably burn in hell
|
25
25
|
for this. You can also use `>` or `>>` if you're going to pass in a proc or
|
26
|
-
|
26
|
+
lambda object.
|
27
|
+
|
28
|
+
`Maybe` and `Either` are applicative functors with the apply operator `*`. Read
|
29
|
+
further to see how it works.
|
27
30
|
|
28
31
|
### Function composition
|
29
32
|
|
@@ -121,6 +124,18 @@ Maybe(user).fmap(&:address).fmap(&:street)
|
|
121
124
|
# => None()
|
122
125
|
```
|
123
126
|
|
127
|
+
### `*` (applicative functor's apply)
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
require "kleisli"
|
131
|
+
|
132
|
+
add = -> x, y { x + y }
|
133
|
+
Some(add) * Some(10) * Some(2)
|
134
|
+
# => Some(12)
|
135
|
+
Some(add) * None() * Some(2)
|
136
|
+
# => None
|
137
|
+
```
|
138
|
+
|
124
139
|
## Try
|
125
140
|
|
126
141
|
The Try monad is useful to express a pipeline of computations that might throw
|
@@ -239,6 +254,18 @@ result # => Right(20)
|
|
239
254
|
result # => Left("wrong")
|
240
255
|
```
|
241
256
|
|
257
|
+
### `*` (applicative functor's apply)
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
require "kleisli"
|
261
|
+
|
262
|
+
add = -> x, y { x + y }
|
263
|
+
Right(add) * Right(10) * Right(2)
|
264
|
+
# => Some(12)
|
265
|
+
Right(add) * Left("error") * Right(2)
|
266
|
+
# => Left("error")
|
267
|
+
```
|
268
|
+
|
242
269
|
### `or`
|
243
270
|
|
244
271
|
`or` does pretty much what would you expect:
|
data/lib/kleisli/either.rb
CHANGED
data/lib/kleisli/maybe.rb
CHANGED
@@ -16,6 +16,14 @@ module Kleisli
|
|
16
16
|
value == other.value
|
17
17
|
end
|
18
18
|
|
19
|
+
def *(other)
|
20
|
+
self >-> f {
|
21
|
+
other >-> val {
|
22
|
+
Maybe.lift(f.arity > 1 ? f.curry.call(val) : f.call(val))
|
23
|
+
}
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
19
27
|
class None < Maybe
|
20
28
|
def fmap(&f)
|
21
29
|
self
|
@@ -28,6 +36,11 @@ module Kleisli
|
|
28
36
|
def or(other)
|
29
37
|
other
|
30
38
|
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
"None"
|
42
|
+
end
|
43
|
+
alias inspect to_s
|
31
44
|
end
|
32
45
|
|
33
46
|
class Some < Maybe
|
@@ -46,6 +59,11 @@ module Kleisli
|
|
46
59
|
def or(other)
|
47
60
|
self
|
48
61
|
end
|
62
|
+
|
63
|
+
def to_s
|
64
|
+
"Some(#{@value})"
|
65
|
+
end
|
66
|
+
alias inspect to_s
|
49
67
|
end
|
50
68
|
end
|
51
69
|
end
|
data/lib/kleisli/version.rb
CHANGED
data/test/kleisli/either_test.rb
CHANGED
@@ -46,4 +46,16 @@ class EitherTest < MiniTest::Unit::TestCase
|
|
46
46
|
def test_pointfree
|
47
47
|
assert_equal Right(10), Right(5) >> F . fn(&Right) . *(2)
|
48
48
|
end
|
49
|
+
|
50
|
+
def test_applicative_functor_right_arity_1
|
51
|
+
assert_equal Right(20), Right(-> x { x * 2 }) * Right(10)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_applicative_functor_right_arity_2
|
55
|
+
assert_equal Right(20), Right(-> x, y { x * y }) * Right(10) * Right(2)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_applicative_functor_left
|
59
|
+
assert_equal Left("error"), Right(-> x, y { x * y }) * Left("error") * Right(2)
|
60
|
+
end
|
49
61
|
end
|
data/test/kleisli/maybe_test.rb
CHANGED
@@ -24,4 +24,16 @@ class MaybeTest < MiniTest::Unit::TestCase
|
|
24
24
|
def test_fmap_some
|
25
25
|
assert_equal Some(6), Some(3).fmap { |x| x * 2 }
|
26
26
|
end
|
27
|
+
|
28
|
+
def test_applicative_functor_some_arity_1
|
29
|
+
assert_equal Some(20), Maybe(-> x { x * 2 }) * Maybe(10)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_applicative_functor_some_arity_2
|
33
|
+
assert_equal Some(20), Maybe(-> x, y { x * y }) * Maybe(10) * Maybe(2)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_applicative_functor_none
|
37
|
+
assert_equal None(), Maybe(-> x, y { x * y }) * None() * Maybe(2)
|
38
|
+
end
|
27
39
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kleisli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josep M. Bach
|
@@ -55,6 +55,7 @@ files:
|
|
55
55
|
- Rakefile
|
56
56
|
- kleisli.gemspec
|
57
57
|
- lib/kleisli.rb
|
58
|
+
- lib/kleisli/applicative_functor.rb
|
58
59
|
- lib/kleisli/blank.rb
|
59
60
|
- lib/kleisli/composition.rb
|
60
61
|
- lib/kleisli/either.rb
|