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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: faefce7df113e758631337927c7a3ec32f0305ff
4
- data.tar.gz: 6e583da161293e7c603163f24dfd6af293c5445b
3
+ metadata.gz: 997aca6d77f858cf9262df7edbc913179cd8004f
4
+ data.tar.gz: dac24d37b400e98703e6299fb6a702ea5df773eb
5
5
  SHA512:
6
- metadata.gz: 24c366c7151184fb84fc42938f4afd1473e75575ff82c7e0ee5255b44bcef9f1ec028c10bd0ac19d84635b6b9ef53c7b6332f8e5e048df2ed9d73833482ca12c
7
- data.tar.gz: b8d1ad6965cfe41ddf33e72af50ac7d4cfbc62b07aa23873625af8981c78a35f5a271aeea14929a76a1894fb26860faba1867af02f5d1c340368815cdf2d28bc
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
- lambda object.
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:
@@ -0,0 +1,4 @@
1
+ module Kleisli
2
+ class ApplicativeFunctor < Functor
3
+ end
4
+ end
@@ -9,6 +9,14 @@ module Kleisli
9
9
  right == other.right && left == other.left
10
10
  end
11
11
 
12
+ def *(other)
13
+ self >-> f {
14
+ other >-> val {
15
+ Right(f.arity > 1 ? f.curry.call(val) : f.call(val))
16
+ }
17
+ }
18
+ end
19
+
12
20
  class Right < Either
13
21
  alias value right
14
22
 
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
@@ -1,3 +1,3 @@
1
1
  module Kleisli
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -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
@@ -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.1.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