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.
- encode : α → ℕ
- decode : ℕ → option α
- encodek : ∀ (a : α), encodable.decode α (encodable.encode a) = some a
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.
An encodable type has decidable equality. Not set as an instance because this is usually not the best way to infer decidability.
Equations
If α
is encodable and there is an injection f : β → α
, then β
is encodable as well.
Equations
- encodable.of_left_injection f finv linv = {encode := λ (b : β), encodable.encode (f b), decode := λ (n : ℕ), (encodable.decode α n).bind finv, encodek := _}
If α
is encodable and f : β → α
is invertible, then β
is encodable as well.
Equations
- encodable.of_left_inverse f finv linv = encodable.of_left_injection f (some ∘ finv) _
Encodability is preserved by equivalence.
Equations
- encodable.of_equiv α e = encodable.of_left_inverse ⇑e ⇑(e.symm) _
If α
is encodable, then so is option α
.
Equations
- encodable.option = {encode := λ (o : option α), o.cases_on 0 (λ (a : α), (encodable.encode a).succ), decode := λ (n : ℕ), n.cases_on (some none) (λ (m : ℕ), option.map some (encodable.decode α m)), encodek := _}
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 (λ (a : α), encodable.encode a = n))
The encoding function has decidable range.
Equations
- encodable.decidable_range_encode α = λ (x : ℕ), decidable_of_iff ↥((encodable.decode₂ α x).is_some) _
An encodable type is equivalent to the range of its encoding function.
Equations
- encodable.equiv_range_encode α = {to_fun := λ (a : α), ⟨encodable.encode a, _⟩, inv_fun := λ (n : ↥(set.range encodable.encode)), option.get _, left_inv := _, right_inv := _}
Explicit encoding function for the sum of two encodable types.
Equations
- encodable.encode_sum (sum.inr b) = bit1 (encodable.encode b)
- encodable.encode_sum (sum.inl a) = bit0 (encodable.encode a)
Explicit decoding function for the sum of two encodable types.
Equations
- encodable.decode_sum n = encodable.decode_sum._match_1 n.bodd_div2
- encodable.decode_sum._match_1 (tt, m) = option.map sum.inr (encodable.decode β m)
- encodable.decode_sum._match_1 (ff, m) = option.map sum.inl (encodable.decode α m)
If α
and β
are encodable, then so is their sum.
Equations
- encodable.sum = {encode := encodable.encode_sum _inst_2, decode := encodable.decode_sum _inst_2, encodek := _}
Explicit encoding function for sigma γ
Equations
- encodable.encode_sigma ⟨a, b⟩ = nat.mkpair (encodable.encode a) (encodable.encode b)
Explicit decoding function for sigma γ
Equations
- encodable.decode_sigma n = encodable.decode_sigma._match_1 (nat.unpair n)
- encodable.decode_sigma._match_1 (n₁, n₂) = (encodable.decode α n₁).bind (λ (a : α), option.map (sigma.mk a) (encodable.decode (γ a) n₂))
Equations
- encodable.sigma = {encode := encodable.encode_sigma (λ (a : α), _inst_2 a), decode := encodable.decode_sigma (λ (a : α), _inst_2 a), encodek := _}
If α
and β
are encodable, then so is their product.
Equations
- encodable.prod = encodable.of_equiv (Σ (_x : α), β) (equiv.sigma_equiv_prod α β).symm
Explicit encoding function for a decidable subtype of an encodable type
Equations
Explicit decoding function for a decidable subtype of an encodable type
Equations
- encodable.decode_subtype v = (encodable.decode α v).bind (λ (a : α), dite (P a) (λ (h : P a), some ⟨a, h⟩) (λ (h : ¬P a), none))
A decidable subtype of an encodable type is encodable.
Equations
- encodable.subtype = {encode := encodable.encode_subtype encA, decode := encodable.decode_subtype (λ (a : α), decP a), encodek := _}
Equations
- encodable.fin n = encodable.of_equiv {m // m < n} (equiv.fin_equiv_subtype n)
Equations
Equations
The lift of an encodable type is encodable.
Equations
The lift of an encodable type is encodable.
Equations
If β
is encodable and there is an injection f : α → β
, then α
is encodable as well.
Equations
- encodable.of_inj f hf = encodable.of_left_injection f (function.partial_inv f) _
The equivalence between the encodable type α
and ulower α : Type
.
Equations
Lowers an a : α
into ulower α
.
Equations
- ulower.down a = ⇑(ulower.equiv α) a
Equations
- ulower.inhabited = {default := ulower.down (default α)}
Constructive choice function for a decidable subtype of an encodable type.
Equations
- encodable.choose_x h = have this : ∃ (n : ℕ), good p (encodable.decode α n), from _, encodable.choose_x._match_4 (encodable.decode α (nat.find this)) _
- encodable.choose_x._match_4 (some a) h = ⟨a, h⟩
- _ = _
Constructive choice function for a decidable predicate over an encodable type.
Equations
The encode
function, viewed as an embedding.
Equations
- encodable.encode' α = {to_fun := encodable.encode _inst_1, inj' := _}
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 (n + 1) = let p : α := directed.sequence f hf n in directed.sequence._match_1 f hf p (encodable.decode α n)
- directed.sequence f hf 0 = default α
- directed.sequence._match_1 f hf p (some a) = classical.some _
- directed.sequence._match_1 f hf p none = classical.some _
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 _
The quotient of an encodable space by a decidable equivalence relation is encodable.
Equations
- encodable_quotient = {encode := λ (q : quotient s), encodable.encode q.rep, decode := λ (n : ℕ), quotient.mk <$> encodable.decode α n, encodek := _}