Encodable types #
This file defines encodable (constructively countable) types as a typeclass.
This is used to provide explicit encode/decode functions from and to ℕ
, with the information that
those functions are inverses of each other.
The difference with Denumerable
is that finite types are encodable. For infinite types,
Encodable
and Denumerable
agree.
Main declarations #
Encodable α
: States that there exists an explicit encoding functionencode : α → ℕ
with a partial inversedecode : ℕ → Option α
.decode₂
: Version ofdecode
that is equal tonone
outside of the range ofencode
. Useful as we do not require this in the definition ofdecode
.ULower α
: Any encodable type has an equivalent type living in the lowest universe, namely a subtype ofℕ
.ULower α
finds it.
Implementation notes #
The point of asking for an explicit partial inverse decode : ℕ → Option α
to encode : α → ℕ
is
to make the range of encode
decidable even when the finiteness of α
is not.
Constructively countable type. Made from an explicit injection encode : α → ℕ
and a partial
inverse decode : ℕ → Option α
. Note that finite types are countable. See Denumerable
if you
wish to enforce infiniteness.
- encode : α → ℕ
Encoding from Type α to ℕ
Decoding from ℕ to Option α
- encodek : ∀ (a : α), Encodable.decode (Encodable.encode a) = some a
Invariant relationship between encoding and decoding
Instances
An encodable type has decidable equality. Not set as an instance because this is usually not the best way to infer decidability.
Equations
- Encodable.decidableEqOfEncodable α x✝ x = decidable_of_iff (Encodable.encode x✝ = Encodable.encode x) ⋯
Instances For
If α
is encodable and there is an injection f : β → α
, then β
is encodable as well.
Equations
- Encodable.ofLeftInjection f finv linv = { encode := fun (b : β) => Encodable.encode (f b), decode := fun (n : ℕ) => (Encodable.decode n).bind finv, encodek := ⋯ }
Instances For
If α
is encodable and f : β → α
is invertible, then β
is encodable as well.
Equations
- Encodable.ofLeftInverse f finv linv = Encodable.ofLeftInjection f (some ∘ finv) ⋯
Instances For
Encodability is preserved by equivalence.
Equations
- Encodable.ofEquiv α e = Encodable.ofLeftInverse ⇑e ⇑e.symm ⋯
Instances For
Equations
- Nat.encodable = { encode := id, decode := some, encodek := Nat.encodable.proof_1 }
Equations
- IsEmpty.toEncodable = { encode := fun (a : α) => isEmptyElim a, decode := fun (x : ℕ) => none, encodek := ⋯ }
Equations
- PUnit.encodable = { encode := fun (x : PUnit.{?u.7 + 1} ) => 0, decode := fun (n : ℕ) => Nat.casesOn n (some PUnit.unit) fun (x : ℕ) => none, encodek := PUnit.encodable.proof_1 }
Failsafe variant of decode
. decode₂ α n
returns the preimage of n
under encode
if it
exists, and returns none
if it doesn't. This requirement could be imposed directly on decode
but
is not to help make the definition easier to use.
Equations
- Encodable.decode₂ α n = (Encodable.decode n).bind (Option.guard fun (a : α) => Encodable.encode a = n)
Instances For
The encoding function has decidable range.
Equations
- Encodable.decidableRangeEncode α x = decidable_of_iff ((Encodable.decode₂ α x).isSome = true) ⋯
Instances For
Explicit encoding function for the sum of two encodable types.
Equations
- Encodable.encodeSum (Sum.inl a) = 2 * Encodable.encode a
- Encodable.encodeSum (Sum.inr b) = 2 * Encodable.encode b + 1
Instances For
Explicit decoding function for the sum of two encodable types.
Equations
- Encodable.decodeSum n = match n.boddDiv2 with | (false, m) => Option.map Sum.inl (Encodable.decode m) | (fst, m) => Option.map Sum.inr (Encodable.decode m)
Instances For
Explicit encoding function for Sigma γ
Equations
- Encodable.encodeSigma ⟨a, b⟩ = Nat.pair (Encodable.encode a) (Encodable.encode b)
Instances For
Explicit decoding function for Sigma γ
Equations
- Encodable.decodeSigma n = match Nat.unpair n with | (n₁, n₂) => (Encodable.decode n₁).bind fun (a : α) => Option.map (Sigma.mk a) (Encodable.decode n₂)
Instances For
If α
and β
are encodable, then so is their product.
Equations
- Encodable.Prod.encodable = Encodable.ofEquiv ((_ : α) × β) (Equiv.sigmaEquivProd α β).symm
Explicit encoding function for a decidable subtype of an encodable type
Equations
- Encodable.encodeSubtype ⟨v, property⟩ = Encodable.encode v
Instances For
Explicit decoding function for a decidable subtype of an encodable type
Equations
- Encodable.decodeSubtype v = (Encodable.decode v).bind fun (a : α) => if h : P a then some ⟨a, h⟩ else none
Instances For
A decidable subtype of an encodable type is encodable.
Equations
- Subtype.encodable = { encode := Encodable.encodeSubtype, decode := Encodable.decodeSubtype, encodek := ⋯ }
Equations
- Fin.encodable n = Encodable.ofEquiv { i : ℕ // i < n } Fin.equivSubtype
Equations
Equations
The lift of an encodable type is encodable
Equations
- ULift.encodable = Encodable.ofEquiv α Equiv.ulift
The lift of an encodable type is encodable.
Equations
- PLift.encodable = Encodable.ofEquiv α Equiv.plift
If β
is encodable and there is an injection f : α → β
, then α
is encodable as well.
Equations
- Encodable.ofInj f hf = Encodable.ofLeftInjection f (Function.partialInv f) ⋯
Instances For
If α
is countable, then it has a (non-canonical) Encodable
structure.
Equations
- Encodable.ofCountable α = ⋯.some
Instances For
Equations
- instDecidableEqULower = id (Encodable.decidableEqOfEncodable ↑(Set.range Encodable.encode))
Equations
- ULower.instInhabited = { default := ULower.down default }
Constructive choice function for a decidable subtype of an encodable type.
Equations
- Encodable.chooseX h = match Encodable.decode (Nat.find ⋯), ⋯ with | some a, h => ⟨a, h⟩
Instances For
Constructive choice function for a decidable predicate over an encodable type.
Equations
- Encodable.choose h = ↑(Encodable.chooseX h)
Instances For
A constructive version of Classical.axiom_of_choice
for Encodable
types.
A constructive version of Classical.skolem
for Encodable
types.
The encode
function, viewed as an embedding.
Equations
- Encodable.encode' α = { toFun := Encodable.encode, inj' := ⋯ }
Instances For
Equations
- ⋯ = ⋯
Equations
- ⋯ = ⋯
Given a Directed r
function f : α → β
defined on an encodable inhabited type,
construct a noncomputable sequence such that r (f (x n)) (f (x (n + 1)))
and r (f a) (f (x (encode a + 1))
.
Equations
- Directed.sequence f hf 0 = default
- Directed.sequence f hf n.succ = match Encodable.decode n with | none => Classical.choose ⋯ | some a => Classical.choose ⋯
Instances For
Representative of an equivalence class. This is a computable version of Quot.out
for a setoid
on an encodable type.
Equations
- q.rep = Encodable.choose ⋯
Instances For
The quotient of an encodable space by a decidable equivalence relation is encodable.
Equations
- encodableQuotient = { encode := fun (q : Quotient s) => Encodable.encode q.rep, decode := fun (n : ℕ) => Quotient.mk'' <$> Encodable.decode n, encodek := ⋯ }