Class: Finitio::UnionType
- Defined in:
- lib/finitio/type/union_type.rb,
lib/finitio/generation/union_type.rb
Overview
A union type (aka algebraic type) allows capturing information types through generalization/disjunction. For instance,
Numeric = Int|Real
This class allows capturing such union types, as follows:
Int = BuiltinType.new(Fixnum)
Real = BuiltinType.new(Float)
Numeric = UnionType.new([ Int, Real ])
When transforming a value through ‘dress`, the different candidate types are tried in specified order. The first one that succeeds at building the value ends the process and the value is simply returned. Accordingly, the concrete representation will be
R(Numeric) = R(Int) ^ R(Real) = Fixnum ^ Float = Numeric
where ‘^` denotes the `least common super type` operator on ruby classes.
Accordingly, the ‘dress` transformation function has the following signature:
dress :: Alpha -> Numeric throws TypeError
dress :: Object -> Numeric throws TypeError
Constant Summary
Constants included from Metadata
Instance Attribute Summary collapse
-
#candidates ⇒ Object
readonly
Returns the value of attribute candidates.
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
- #default_name ⇒ Object
-
#dress(value, handler = DressHelper.new) ⇒ Object
Invoke ‘dress` on each candidate type in turn.
- #generate_data(generator, world = nil) ⇒ Object
- #hash ⇒ Object
- #include?(value) ⇒ Boolean
-
#initialize(candidates, name = nil, metadata = nil) ⇒ UnionType
constructor
A new instance of UnionType.
- #representator ⇒ Object
- #resolve_proxies(system) ⇒ Object
- #suppremum(other) ⇒ Object (also: #_suppremum)
- #unconstrained ⇒ Object
Methods inherited from Type
#anonymous?, #name, #name=, #named?, #to_s
Methods included from Metadata
#metadata, #metadata=, #metadata?
Constructor Details
#initialize(candidates, name = nil, metadata = nil) ⇒ UnionType
Returns a new instance of UnionType.
32 33 34 35 36 37 38 39 |
# File 'lib/finitio/type/union_type.rb', line 32 def initialize(candidates, name = nil, = nil) unless candidates.all?{|c| c.is_a?(Type) } raise ArgumentError, "[Finitio::Type] expected, got #{candidates}" end super(name, ) @candidates = candidates.freeze end |
Instance Attribute Details
#candidates ⇒ Object (readonly)
Returns the value of attribute candidates.
40 41 42 |
# File 'lib/finitio/type/union_type.rb', line 40 def candidates @candidates end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
84 85 86 87 88 |
# File 'lib/finitio/type/union_type.rb', line 84 def ==(other) super || ( other.is_a?(UnionType) && set_equal?(candidates, other.candidates) ) end |
#default_name ⇒ Object
69 70 71 |
# File 'lib/finitio/type/union_type.rb', line 69 def default_name candidates.map(&:name).join('|') end |
#dress(value, handler = DressHelper.new) ⇒ Object
Invoke ‘dress` on each candidate type in turn. Return the value returned by the first one that does not fail. Fail with an TypeError if no candidate succeeds at tranforming `value`.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/finitio/type/union_type.rb', line 53 def dress(value, handler = DressHelper.new) error = nil # Do nothing on TypeError as the next candidate could be the good one! candidates.each do |c| success, uped = handler.just_try do c.dress(value, handler) end return uped if success error ||= uped end # No one succeed, just fail handler.failed!(self, value, error) end |
#generate_data(generator, world = nil) ⇒ Object
4 5 6 7 |
# File 'lib/finitio/generation/union_type.rb', line 4 def generate_data(generator, world = nil) picked = generator.flip_one_out_of(candidates) generator.call(picked, world) end |
#hash ⇒ Object
91 92 93 |
# File 'lib/finitio/type/union_type.rb', line 91 def hash self.class.hash ^ set_hash(self.candidates) end |
#include?(value) ⇒ Boolean
46 47 48 |
# File 'lib/finitio/type/union_type.rb', line 46 def include?(value) candidates.any?{|c| c.include?(value) } end |
#representator ⇒ Object
42 43 44 |
# File 'lib/finitio/type/union_type.rb', line 42 def representator raise NotImplementedError end |
#resolve_proxies(system) ⇒ Object
95 96 97 |
# File 'lib/finitio/type/union_type.rb', line 95 def resolve_proxies(system) UnionType.new(candidates.map{|t| t.resolve_proxies(system)}, name, ) end |