ruby-monads 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
  SHA256:
3
- metadata.gz: 20b2534e81fe4b81311ea0dc9b9ab696edab9a2cffc124ef922bb9d26edc87b8
4
- data.tar.gz: 050a8dea7bfeb6dea6b6635c90ce216968208d73346023440ef4410cbdd00e62
3
+ metadata.gz: 1af43d29c4276218767541b961ca19fb65e5f48c35cfd880f33fd47a23a5c7e4
4
+ data.tar.gz: 3da1575ae115a6c572720550a4b08b651ceaa04b75d43a9d643f8658e3b28f9a
5
5
  SHA512:
6
- metadata.gz: 0a8ce58d40d7c361e1e860c1700b5edbbbb927698449ecddc412fdd3ce6f3bc3f3bd1e923ef62ab33fd7f92e13fc3b7f1afb7e7d7cfb79337bda0cfcb9aacf19
7
- data.tar.gz: 604d7fddc645a0e08591d192736339eacc17174a39f3d4b58500c4aaa9df19b02c5917cd7cc6f0cfcfeedb5ee62ca2673fd611e00216d603671ec6e174ec00ee
6
+ metadata.gz: 53328e008e31ecb7d4f08323e1c6665d7e93fbf72224cf5ee29b573e88bba14b4c67b9e740948ecd458281b48269589a8cd903144eb3ec2110981b1430e8e13d
7
+ data.tar.gz: e33053dfad28ca2ba867061f35121e139c7aef399971fa8c92128840d16951c636526dbf8979cae712dc37e9a0befd70cd061f2b6d357bddd3181933bf892a6a
data/README.md CHANGED
@@ -30,20 +30,41 @@ The maybe monad returns one of the following classes, wether it wraps a value or
30
30
  #### Examples
31
31
 
32
32
  ```ruby
33
- just = Maybe.unit("Hello, World!") # => #<Monads::Just @value="Hello, World!">
34
- nothing = Maybe.unit(nil) # => #<Monads::Nothing>
35
-
36
- just.upcase # => #<Monads::Just @value="HELLO, WORLD!">
37
- just.upcase.split.unwrap([]) # => ["HELLO,", "WORLD!"]
38
- just.bind { |v| Maybe.unit(nil) } # => #<Monads::Nothing>
39
- just.fmap { |v| v.gsub(/\w/, "*") } # => #<Monads::Just @value="*****, *****!">
40
- Maybe.unit(just).join # => #<Monads::Just @value="Hello, World!">
41
-
42
- nothing.upcase # => #<Monads::Nothing>
43
- nothing.upcase.split.unwrap([]) # => []
44
- nothing.bind { |v| just } # => #<Monads::Nothing>
45
- nothing.fmap { |v| v.gsub(/\w/, "*") } # => #<Monads::Nothing>
46
- Maybe.unit(nothing).join # => #<Monads::Nothing>
33
+ Maybe.unit("Hello, World!") # => #<Monads::Just @value="Hello, World!">
34
+ Maybe.unit(nil) # => #<Monads::Nothing>
35
+
36
+ Maybe.unit("Hello, World!").upcase # => #<Monads::Just @value="HELLO, WORLD!">
37
+ Maybe.unit("Hello, World!").upcase.split.unwrap([]) # => ["HELLO,", "WORLD!"]
38
+ Maybe.unit("Hello, World!").bind { |v| Maybe.unit(nil) } # => #<Monads::Nothing>
39
+ Maybe.unit("Hello, World!").fmap { |v| v.gsub(/\w/, "*") } # => #<Monads::Just @value="*****, *****!">
40
+ Maybe.unit(Maybe.unit("Hello, World!")).join # => #<Monads::Just @value="Hello, World!">
41
+
42
+ Maybe.unit(nil).upcase # => #<Monads::Nothing>
43
+ Maybe.unit(nil).upcase.split.unwrap([]) # => []
44
+ Maybe.unit(nil).bind { |v| Maybe.unit("Hello, World!") } # => #<Monads::Maybe.unit(nil)>
45
+ Maybe.unit(nil).fmap { |v| v.gsub(/\w/, "*") } # => #<Monads::Nothing>
46
+ Maybe.unit(Maybe.unit(nil)).join # => #<Monads::Nothing>
47
+ ```
48
+
49
+ ### Result
50
+
51
+ The result monad returns one of the following classes, wether it wraps an error or not:
52
+
53
+ - `Result.unit(42)` returns an instance of `Success` wrapping the `42` value
54
+ - `Result.unit(StandardError.new)` returns an instance of `Failure` wrapping the given error
55
+
56
+ #### Examples
57
+
58
+ ```ruby
59
+ Result.unit("Hello, World!") # => #<Monads::Success @value="Hello, World!">
60
+ Result.unit(StandardError.new("Wrong!")) # => #<Monads::Failure @value=#<StandardError: Wrong!>>
61
+
62
+ Result
63
+ .unit("Hello, World!") # => #<Monads::Success @value="Hello, World!">
64
+ .upcase # => #<Monads::Success @value="HELLO, WORLD!">
65
+ .even # => #<Monads::Failure @value=#<NoMethodError: undefined method `even?' for "HELLO, WORLD!":String>>
66
+ .split # => #<Monads::Failure @value=#<NoMethodError: undefined method `even?' for "HELLO, WORLD!":String>>
67
+ .unwrap("default") # "default"
47
68
  ```
48
69
 
49
70
  ## Why this gem
@@ -6,7 +6,13 @@ module Monads
6
6
 
7
7
  # unit :: a -> M a
8
8
  def self.unit(value)
9
- value.is_a?(FAILURE_TRIGGER) ? Failure.new(value) : Success.new(value)
9
+ if value.is_a?(FAILURE_TRIGGER) || value.is_a?(Failure)
10
+ Failure.new(value)
11
+ else
12
+ Success.new(value)
13
+ end
14
+ rescue => error
15
+ Failure.new(error)
10
16
  end
11
17
 
12
18
  # bind :: (a -> M b) -> M a -> M b
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "ruby-monads"
3
- s.version = "0.1.0"
3
+ s.version = "0.2.0"
4
4
  s.summary = "Some common monads"
5
5
  s.description = "Simple and minimalist ruby implementation of some common monads"
6
6
  s.author = "Guillaume BOUDON"
@@ -0,0 +1,63 @@
1
+ print "\n\"Result\" monad test suite"
2
+
3
+ setup do
4
+ [Success.new(42), Failure.new(StandardError.new("Wrong!"))]
5
+ end
6
+
7
+ test "Result::new" do
8
+ assert_raise NoMethodError do Result.new(42) end
9
+
10
+ assert_raise TypeError do Success.new(StandardError.new) end
11
+ assert Success.new(42).is_a?(Success)
12
+
13
+ assert_raise TypeError do Failure.new(42) end
14
+ assert Failure.new(StandardError.new).is_a?(Failure)
15
+ end
16
+
17
+ test "Result::unit" do |success, failure|
18
+ assert success.is_a?(Result)
19
+ assert success.is_a?(Success)
20
+ assert !success.is_a?(Failure)
21
+
22
+ assert failure.is_a?(Result)
23
+ assert !failure.is_a?(Success)
24
+ assert failure.is_a?(Failure)
25
+
26
+ assert Result.unit(success).is_a?(Success)
27
+ assert Result.unit(failure).is_a?(Failure)
28
+ end
29
+
30
+ test "Result#bind" do |success, failure|
31
+ assert success.bind { |v| Result.unit(v / 2) }.is_a?(Success)
32
+ assert success.bind { |v| Result.unit(v / 0) }.is_a?(Failure)
33
+ assert success.bind { |v| v / 0 }.is_a?(Failure)
34
+
35
+ assert failure.bind { |v| Result.unit(42) }.is_a?(Failure)
36
+ assert failure.bind { |v| Result.unit(StandardError.new) }.is_a?(Failure)
37
+ assert failure.bind { |v| v / 2 }.is_a?(Failure)
38
+ end
39
+
40
+ test "Result#fmap" do |success, failure|
41
+ assert success.fmap(&:even?).is_a?(Success)
42
+ assert success.fmap { |v| v / 0 }.is_a?(Failure)
43
+
44
+ assert failure.fmap(&:even?).is_a?(Failure)
45
+ assert failure.fmap { |v| v / 0 }.is_a?(Failure)
46
+ end
47
+
48
+ test "Result#join" do |success, failure|
49
+ assert_equal Result.unit(success).join.unwrap("default"), 42
50
+ assert_equal Result.unit(failure).join.unwrap("default"), "default"
51
+ end
52
+
53
+ test "Result#unwrap" do |success, failure|
54
+ assert_equal success.unwrap("default"), 42
55
+ assert_equal success.unwrap(nil), 42
56
+ assert_equal failure.unwrap("default"), "default"
57
+ assert_equal failure.unwrap(nil), nil
58
+ end
59
+
60
+ test "Result accepts methods chaining" do |success, failure|
61
+ assert_equal success.next.div(13).to_f.unwrap(1.0), 3.0
62
+ assert_equal failure.next.div(13).to_f.unwrap(1.0), 1.0
63
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-monads
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
  - Guillaume BOUDON
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-07 00:00:00.000000000 Z
11
+ date: 2020-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cutest
@@ -48,6 +48,7 @@ files:
48
48
  - ruby-monads.gemspec
49
49
  - test/helper.rb
50
50
  - test/maybe_test.rb
51
+ - test/result_test.rb
51
52
  homepage: https://github.com/guillaumeboudon/ruby-monads
52
53
  licenses:
53
54
  - MIT