Module: Plumb::Conjunction
- Included in:
- And, Intersection
- Defined in:
- lib/plumb/conjunction.rb
Overview
The runtime shared by And (sequential composition) and
Intersection (the lattice meet). Both execute as left then right;
they differ only in how types flow, which each class defines.
They must be separate nodes because the two roles disagree about identity: a
COMPOSITION is a morphism, identified by what it PRODUCES (like a Function),
while an INTERSECTION is a type, identified by itself and subject to the meet
rule ((a ∧ b) <= c when either conjunct is). Applying the meet rule to a
composition is unsound — it makes String >> (String -> Integer) a subtype of
String as well as Integer, two disjoint types.
Instance Attribute Summary collapse
-
#children ⇒ Object
readonly
Returns the value of attribute children.
-
#input_type ⇒ Object
readonly
Returns the value of attribute input_type.
-
#output_type ⇒ Object
readonly
Returns the value of attribute output_type.
Class Method Summary collapse
-
.build(left, right) ⇒ Intersection, And
An Intersection exactly when neither side changes the value (a refinement: both sides narrow one value, order irrelevant); otherwise a pipeline whose ends differ, an And.
Instance Method Summary collapse
- #call(result) ⇒ Object
-
#with_children(children) ⇒ Object
Rebuilds by RECLASSIFYING: a rewrite that swaps a check for a conversion turns a meet into a composition, and preserving the class would leave an Intersection lying about #value_preserving?, which every reduction gates on.
Instance Attribute Details
#children ⇒ Object (readonly)
Returns the value of attribute children.
34 35 36 |
# File 'lib/plumb/conjunction.rb', line 34 def children @children end |
#input_type ⇒ Object (readonly)
Returns the value of attribute input_type.
34 35 36 |
# File 'lib/plumb/conjunction.rb', line 34 def input_type @input_type end |
#output_type ⇒ Object (readonly)
Returns the value of attribute output_type.
34 35 36 |
# File 'lib/plumb/conjunction.rb', line 34 def output_type @output_type end |
Class Method Details
.build(left, right) ⇒ Intersection, And
An Intersection exactly when neither side changes the value (a refinement: both sides narrow one value, order irrelevant); otherwise a pipeline whose ends differ, an And.
The single decision point — every construction site routes through here, so
the distinction is settled once rather than re-derived from
#value_preserving? at each use site.
26 27 28 29 30 31 32 |
# File 'lib/plumb/conjunction.rb', line 26 def self.build(left, right) if Plumb::Subtyping.value_preserving?(left) && Plumb::Subtyping.value_preserving?(right) Intersection.new(left, right) else And.new(left, right) end end |
Instance Method Details
#call(result) ⇒ Object
36 37 38 |
# File 'lib/plumb/conjunction.rb', line 36 def call(result) result.map(@left).map(@right) end |
#with_children(children) ⇒ Object
Rebuilds by RECLASSIFYING: a rewrite that swaps a check for a conversion turns a meet into a composition, and preserving the class would leave an Intersection lying about #value_preserving?, which every reduction gates on.
44 |
# File 'lib/plumb/conjunction.rb', line 44 def with_children(children) = Conjunction.build(children[0], children[1]) |