Class: Rigor::Type::Difference

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/type/difference.rb

Overview

‘Difference[base, removed]` — the value set of `base` minus the value set of `removed`. Implements the point-removal half of the OQ3 refinement-carrier strategy ([ADR-3](docs/adr/3-type-representation.md), Working Decision Option C):

non-empty-string   = Difference[Nominal[String], Constant[""]]
non-zero-int       = Difference[Nominal[Integer], Constant[0]]
non-empty-array[T] = Difference[Nominal[Array, [T]], Tuple[]]
non-empty-hash[K,V] = Difference[Nominal[Hash, [K,V]], HashShape{}]

The carrier itself is structural: it stores ‘base` and `removed` as inner `Type` references and answers projection / acceptance / display questions by composing those inner answers per the lattice algebra in [`value-lattice.md`](docs/type-specification/value-lattice.md). The canonical-name registry (display side) lives in `Rigor::Type::Combinator` and prints kebab-case names like `non-empty-string` for the recognised shapes; unrecognised differences fall back to the raw `base - removed` operator form per [`type-operators.md`](docs/type-specification/type-operators.md).

Construction goes through ‘Type::Combinator.difference` / `Combinator.non_empty_string` etc. — direct `.new` calls are an internal contract; callers MUST ensure both bounds are valid `Rigor::Type` values and that `removed` is a subtype-or-equal of `base` (otherwise the difference does not narrow anything and a normalisation upstream should collapse to `base`).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base, removed) ⇒ Difference

Returns a new instance of Difference.



39
40
41
42
43
# File 'lib/rigor/type/difference.rb', line 39

def initialize(base, removed)
  @base = base
  @removed = removed
  freeze
end

Instance Attribute Details

#baseObject (readonly)

Returns the value of attribute base.



37
38
39
# File 'lib/rigor/type/difference.rb', line 37

def base
  @base
end

#removedObject (readonly)

Returns the value of attribute removed.



37
38
39
# File 'lib/rigor/type/difference.rb', line 37

def removed
  @removed
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



74
75
76
# File 'lib/rigor/type/difference.rb', line 74

def ==(other)
  other.is_a?(Difference) && base == other.base && removed == other.removed
end

#accepts(other, mode: :gradual) ⇒ Object



70
71
72
# File 'lib/rigor/type/difference.rb', line 70

def accepts(other, mode: :gradual)
  Inference::Acceptance.accepts(self, other, mode: mode)
end

#botObject



62
63
64
# File 'lib/rigor/type/difference.rb', line 62

def bot
  Trinary.no
end

#describe(verbosity = :short) ⇒ Object



45
46
47
48
49
50
# File 'lib/rigor/type/difference.rb', line 45

def describe(verbosity = :short)
  named = canonical_name
  return named if named

  "#{base.describe(verbosity)} - #{removed.describe(verbosity)}"
end

#dynamicObject



66
67
68
# File 'lib/rigor/type/difference.rb', line 66

def dynamic
  base.respond_to?(:dynamic) ? base.dynamic : Trinary.no
end

#erase_to_rbsObject

Erases to the base nominal: every refinement MUST erase to its base per [‘rbs-erasure.md`](docs/type-specification/rbs-erasure.md).



54
55
56
# File 'lib/rigor/type/difference.rb', line 54

def erase_to_rbs
  base.erase_to_rbs
end

#hashObject



79
80
81
# File 'lib/rigor/type/difference.rb', line 79

def hash
  [Difference, base, removed].hash
end

#inspectObject



83
84
85
# File 'lib/rigor/type/difference.rb', line 83

def inspect
  "#<Rigor::Type::Difference #{describe(:short)}>"
end

#topObject



58
59
60
# File 'lib/rigor/type/difference.rb', line 58

def top
  Trinary.no
end