Class: Rigor::Type::Intersection
- Inherits:
-
Object
- Object
- Rigor::Type::Intersection
- Defined in:
- lib/rigor/type/intersection.rb
Overview
‘Intersection[M1, M2, …]` — value set is the meet of every member’s value set. The carrier composes refinements that share a base, in particular the catalogued ‘non-empty-lowercase-string` (= `Difference[String, “”] & Refined[String, :lowercase]`) and `non-empty-uppercase-string` shapes from [`imported-built-in-types.md`](docs/type-specification/imported-built-in-types.md). See [ADR-3](docs/adr/3-type-representation.md) for the OQ3 working decision and the rationale for keeping Intersection a thin wrapper rather than per-shape carriers.
Construction MUST go through ‘Type::Combinator.intersection` (or the per-name factories `Combinator.non_empty_lowercase_string` / `Combinator.non_empty_uppercase_string`). The factory:
-
flattens nested intersections,
-
drops ‘Top` members (Top is the identity of intersection),
-
collapses to ‘Bot` if any member is `Bot` (Bot is absorbing),
-
deduplicates structurally-equal members,
-
sorts the surviving members by ‘describe(:short)` so two structurally-equal intersections built in different orders compare equal,
-
returns ‘Top` for the empty intersection,
-
returns the lone member for a 1-element intersection (so the carrier is never inhabited by a degenerate single-member shape).
Direct ‘.new` callers MUST pass an already-normalised member list and are expected to be tests or the combinator itself.
Instance Attribute Summary collapse
-
#members ⇒ Object
readonly
Returns the value of attribute members.
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
- #accepts(other, mode: :gradual) ⇒ Object
- #bot ⇒ Object
- #describe(verbosity = :short) ⇒ Object
- #dynamic ⇒ Object
-
#erase_to_rbs ⇒ Object
An intersection of refinements over the same base type erases to that base.
- #hash ⇒ Object
-
#initialize(members) ⇒ Intersection
constructor
A new instance of Intersection.
- #inspect ⇒ Object
- #top ⇒ Object
Constructor Details
#initialize(members) ⇒ Intersection
Returns a new instance of Intersection.
40 41 42 43 |
# File 'lib/rigor/type/intersection.rb', line 40 def initialize(members) @members = members.dup.freeze freeze end |
Instance Attribute Details
#members ⇒ Object (readonly)
Returns the value of attribute members.
38 39 40 |
# File 'lib/rigor/type/intersection.rb', line 38 def members @members end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
79 80 81 |
# File 'lib/rigor/type/intersection.rb', line 79 def ==(other) other.is_a?(Intersection) && members == other.members end |
#accepts(other, mode: :gradual) ⇒ Object
75 76 77 |
# File 'lib/rigor/type/intersection.rb', line 75 def accepts(other, mode: :gradual) Inference::Acceptance.accepts(self, other, mode: mode) end |
#describe(verbosity = :short) ⇒ Object
45 46 47 48 49 50 |
# File 'lib/rigor/type/intersection.rb', line 45 def describe(verbosity = :short) named = canonical_name return named if named members.map { |m| m.describe(verbosity) }.join(" & ") end |
#dynamic ⇒ Object
71 72 73 |
# File 'lib/rigor/type/intersection.rb', line 71 def dynamic Trinary.no end |
#erase_to_rbs ⇒ Object
An intersection of refinements over the same base type erases to that base. We use the first member’s erasure because the v0.0.4 catalogue (‘non-empty-lowercase-string` etc.) is restricted to same-base composition; richer cross-base intersections will need a stricter erasure rule (likely “lowest common ancestor” via the inference engine’s class hierarchy).
59 60 61 |
# File 'lib/rigor/type/intersection.rb', line 59 def erase_to_rbs members.first.erase_to_rbs end |
#hash ⇒ Object
84 85 86 |
# File 'lib/rigor/type/intersection.rb', line 84 def hash [Intersection, members].hash end |
#inspect ⇒ Object
88 89 90 |
# File 'lib/rigor/type/intersection.rb', line 88 def inspect "#<Rigor::Type::Intersection #{describe(:short)}>" end |