ruby-monads 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
  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