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

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#childrenObject (readonly)

Returns the value of attribute children.



34
35
36
# File 'lib/plumb/conjunction.rb', line 34

def children
  @children
end

#input_typeObject (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_typeObject (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.

Parameters:

Returns:



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.

See Also:



44
# File 'lib/plumb/conjunction.rb', line 44

def with_children(children) = Conjunction.build(children[0], children[1])