kleisli 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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