···11# frozen_string_literal: true
2233class Literal::Either
44+ def initialize(left_type, right_type)
55+ @left_type = left_type
66+ @right_type = right_type
77+ end
88+99+ def inspect
1010+ "Either(#{@left_type.inspect}, #{@right_type.inspect})"
1111+ end
1212+1313+ def ===(either)
1414+ case either
1515+ when Literal::Left
1616+ @left_type === either.value
1717+ when Literal::Right
1818+ @right_type === either.value
1919+ else
2020+ false
2121+ end
2222+ end
2323+2424+ def new(value)
2525+ case value
2626+ when @left_type
2727+ Literal::Left.new(value)
2828+ when @right_type
2929+ Literal::Right.new(value)
3030+ else
3131+ raise Literal::TypeError,
3232+ "Expected `#{value.inspect}` to be either `#{@left_type.inspect}` or `#{@right_type.inspect}`."
3333+ end
3434+ end
435end
···11# frozen_string_literal: true
2233module Literal::Types
44+ include Literal::Monads
55+46 def _Union(*types)
57 raise Literal::ArgumentError, "Union type must have at least two types." if types.size < 2
68
+1-1
lib/literal/types/interface_type.rb
···1010 end
11111212 def ===(other)
1313- @methods.all? { |method| other.respond_to?(method) }
1313+ @methods.all? { |m| other.respond_to?(m) }
1414 end
1515end
+4
lib/literal/types/union_type.rb
···1212 def ===(value)
1313 @types.any? { |type| type === value }
1414 end
1515+1616+ def nil?
1717+ @types.any?(&:nil?)
1818+ end
1519end
+31
test/literal/either.rb
···11+# frozen_string_literal: true
22+33+include Literal::Monads
44+55+describe "Either(Integer, String)" do
66+ let def either = Either(Integer, String)
77+88+ let def left = either.new(1)
99+ let def right = either.new("foo")
1010+1111+ test "left" do
1212+ expect(left).to_be :left?
1313+ expect(right).not_to_be :left?
1414+ end
1515+1616+ test "right" do
1717+ expect(right).to_be :right?
1818+ expect(left).not_to_be :right?
1919+ end
2020+2121+ test "===" do
2222+ assert either === left
2323+ assert either === right
2424+2525+ refute either === 1
2626+ refute either === "foo"
2727+2828+ refute either === Literal::Left.new("foo")
2929+ refute either === Literal::Right.new(1)
3030+ end
3131+end
+9-8
test/literal/operation.rb
···11# frozen_string_literal: true
22+# # frozen_string_literal: true
2333-class SomeOperation < Literal::Operation
44- def call
55- end
66-end
44+# class SomeOperation < Literal::Operation
55+# def call
66+# end
77+# end
7888-test do
99- result = SomeOperation.call
1010- binding.irb
1111-end
99+# test do
1010+# result = SomeOperation.call
1111+# binding.irb
1212+# end
+42
test/literal/result.rb
···11+# frozen_string_literal: true
22+33+include Literal::Monads
44+55+describe "Result(String)" do
66+ let def result = Result(String)
77+ let def success = result.new("Foo")
88+ let def failure
99+ result.new(
1010+ StandardError.new("Bar")
1111+ )
1212+ end
1313+1414+ describe ".try" do
1515+ test "with correct type" do
1616+ expect(result.try { "Foo" }).to_be :success?
1717+ end
1818+1919+ test "with incorrect type" do
2020+ expect(result.try { 1 }).to_be :failure?
2121+ end
2222+2323+ test "with raise" do
2424+ expect(result.try { raise }).to_be :failure?
2525+ end
2626+ end
2727+2828+ test "#success?" do
2929+ expect(success).to_be :success?
3030+ expect(failure).not_to_be :success?
3131+ end
3232+3333+ test "#failure?" do
3434+ expect(failure).to_be :failure?
3535+ expect(success).not_to_be :failure?
3636+ end
3737+3838+ test "#inspect" do
3939+ expect(success.inspect) == %(Literal::Success("Foo"))
4040+ expect(failure.inspect) == "Literal::Failure(#<StandardError: Bar>)"
4141+ end
4242+end