···149149attribute :thing, _Any
150150```
151151152152-To make this argument optional and allow `nil`, you could use use `_Maybe`.
152152+To make this argument optional and allow `nil`, you could use use `_Nilable`.
153153154154-### `_Maybe(T)`
154154+### `_Nilable(T)`
155155156156-The `_Maybe` type is a union of `nil` and the specified type `T`. It’s literally `_Union(T, nil)`.
156156+The `_Nilable` type is a union of `nil` and the specified type `T`. It’s literally `_Union(T, nil)`.
157157158158```ruby
159159-attribute :thing, _Maybe(_Any)
159159+attribute :thing, _Nilable(_Any)
160160```
161161162162### `_Boolean`
+5-29
lib/literal/either.rb
···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
44+ def initialize(value)
55+ @value = value
66+ freeze
227 end
2382424- 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
99+ attr_reader :value
1010+ attr_accessor :type
3511end
···11+# frozen_string_literal: true
22+33+class Literal::EitherType
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
3535+end
+1-1
lib/literal/failure.rb
···11# frozen_string_literal: true
2233-class Literal::Failure < Literal::Result::Option
33+class Literal::Failure < Literal::Result
44 def initialize(value)
55 @value = case value
66 when StandardError
···11+# frozen_string_literal: true
22+33+class Literal::MaybeType
44+ def initialize(type)
55+ @type = type
66+ end
77+88+ def inspect
99+ "Maybe(#{@type.inspect})"
1010+ end
1111+1212+ def new(value)
1313+ case value
1414+ when nil
1515+ Literal::Nothing
1616+ when @type
1717+ Literal::Some.new(value)
1818+ else
1919+ raise Literal::TypeError, "Expected `#{value.inspect}` to be `#{@type.inspect}`."
2020+ end
2121+ end
2222+2323+ def ===(maybe)
2424+ case maybe
2525+ when Literal::Nothing
2626+ true
2727+ when Literal::Some
2828+ @type === maybe.value
2929+ else
3030+ false
3131+ end
3232+ end
3333+end
+13-19
lib/literal/monads.rb
···11# frozen_string_literal: true
2233module Literal::Monads
44- Nothing = Literal::Nothing.new
55- Optional = Nothing # `Maybe` called without anything, e.g. `Maybe(something)` is Nothing
66-77- def Some(thing)
88- Literal::Some.new(thing)
99- end
44+ Nothing = Literal::Nothing
55+ Left = Literal::Left
66+ Right = Literal::Right
77+ Some = Literal::Some
1081111- def Optional(value)
1212- value.nil? ? Nothing : Some(value)
99+ def Maybe(type)
1010+ Literal::MaybeType.new(type)
1311 end
14121513 def Either(left_type, right_type)
1616- Literal::Either.new(left_type, right_type)
1717- end
1818-1919- def Left(value)
2020- Literal::Left.new(value)
1414+ Literal::EitherType.new(left_type, right_type)
2115 end
22162323- def Right(value)
2424- Literal::Right.new(value)
1717+ def Result(type)
1818+ Literal::ResultType.new(type)
2519 end
26202727- def Result(type)
2828- Literal::Result.new(type)
2121+ def Try(type, &block)
2222+ Literal::ResultType.new(type).try(&block)
2923 end
30243131- def Try(type, &)
3232- Literal::Result.new(type).try(&)
2525+ def Some(type)
2626+ Literal::SomeType.new(type)
3327 end
3428end
+2-28
lib/literal/nothing.rb
···11# frozen_string_literal: true
2233-class Literal::Nothing < Literal::Optional::Option
44- def initialize
55- freeze
66- end
77-88- def empty? = true
99- def inspect = "Nothing"
1010-1111- def value_or(fallback)
1212- fallback
1313- end
1414-1515- def map
1616- self
1717- end
1818-1919- def flat_map
2020- self
2121- end
2222-2323- def or_else(alternative)
2424- if alternative.nil?
2525- self
2626- else
2727- Some(alternative)
2828- end
2929- end
3030-end
33+Literal::Nothing = Literal::NothingClass.new
44+Literal.private_constant(:NothingClass)
+34
lib/literal/nothing_class.rb
···11+# frozen_string_literal: true
22+33+class Literal::NothingClass < Literal::Maybe
44+ def initialize
55+ freeze
66+ end
77+88+ def empty? = true
99+ def inspect = "Nothing"
1010+1111+ def value_or(fallback)
1212+ fallback
1313+ end
1414+1515+ def map
1616+ self
1717+ end
1818+1919+ def flat_map
2020+ self
2121+ end
2222+2323+ def or(alternative)
2424+ if alternative.nil?
2525+ raise Literal::TypeError, "Alternative cannot be nil."
2626+ end
2727+2828+ if alternative.nil?
2929+ self
3030+ else
3131+ Literal::Some.new(alternative)
3232+ end
3333+ end
3434+end
-22
lib/literal/optional.rb
···11-# frozen_string_literal: true
22-33-class Literal::Optional
44- def initialize(type)
55- @type = type
66- end
77-88- def inspect
99- "Optional(#{@type.inspect})"
1010- end
1111-1212- def ===(optional)
1313- case optional
1414- when Literal::None
1515- true
1616- when Literal::Some
1717- @type === optional.value
1818- else
1919- false
2020- end
2121- end
2222-end
···11+# frozen_string_literal: true
22+33+class Literal::SomeType
44+ def initialize(type)
55+ @type = type
66+ end
77+88+ def inspect
99+ "Some(#{@type.inspect})"
1010+ end
1111+1212+ def ===(other)
1313+ case other
1414+ when Literal::Some
1515+ @type === other.value
1616+ else
1717+ false
1818+ end
1919+ end
2020+2121+ def new(value)
2222+ case value
2323+ when @type
2424+ Literal::Some.new(value)
2525+ else
2626+ raise Literal::TypeError, "Expected `#{value.inspect}` to be `#{@type.inspect}`."
2727+ end
2828+ end
2929+end
···3131 Literal::Types::InterfaceType.new(*methods)
3232 end
33333434- def _Maybe(type)
3434+ def _Nilable(type)
3535 _Union(type, nil)
3636 end
3737
+10-10
test/literal/either.rb
···88 let def left = either.new(1)
99 let def right = either.new("foo")
10101111- 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-2111 test "===" do
2212 assert either === left
2313 assert either === right
···27172818 refute either === Literal::Left.new("foo")
2919 refute either === Literal::Right.new(1)
2020+ end
2121+2222+ test "#left?" do
2323+ expect(left).to_be :left?
2424+ expect(right).not_to_be :left?
2525+ end
2626+2727+ test "#right?" do
2828+ expect(right).to_be :right?
2929+ expect(left).not_to_be :right?
3030 end
3131end