module Data.Maybe.Properties where
Properties of Maybeπ
Path spaceπ
We can use these lemmas to characterise the path space of
Maybe A
in terms of the path space of A
. This
involves a standard encode-decode argument: for a more in-depth
explanation, see Data.List
.
module MaybePath {β} {A : Type β} where Code : Maybe A β Maybe A β Type _ Code (just x) (just y) = x β‘ y Code (just x) nothing = Lift _ β₯ Code nothing (just y) = Lift _ β₯ Code nothing nothing = Lift _ β€
The rest of this argument is standard, so we omit it.
refl-code : β x β Code x x refl-code (just x) = refl refl-code nothing = lift tt decode : β x y β Code x y β x β‘ y decode (just x) (just y) p = ap just p decode nothing nothing _ = refl encode : β x y β x β‘ y β Code x y encode (just x) (just y) p = just-inj p encode (just x) nothing p = absurd (justβ nothing p) encode nothing (just x) p = absurd (nothingβ just p) encode nothing nothing p = lift tt encode-refl : β {x} β encode x x refl β‘ refl-code x encode-refl {x = just x} = refl encode-refl {x = nothing} = refl decode-refl : β {x} β decode x x (refl-code x) β‘ refl decode-refl {x = just x} = refl decode-refl {x = nothing} = refl decode-encode : β {x y} β (p : x β‘ y) β decode x y (encode x y p) β‘ p decode-encode {x = x} = J (Ξ» y' p β decode x y' (encode x y' p) β‘ p) (ap (decode x x) encode-refl β decode-refl) encode-decode : β {x y} β (p : Code x y) β encode x y (decode x y p) β‘ p encode-decode {just x} {just y} p = refl encode-decode {nothing} {nothing} p = refl PathβCode : β x y β (x β‘ y) β Code x y PathβCode x y = IsoβEquiv (encode x y , iso (decode x y) encode-decode decode-encode) Code-is-hlevel : {x y : Maybe A} (n : Nat) β is-hlevel A (2 + n) β is-hlevel (Code x y) (1 + n) Code-is-hlevel {x = just x} {y = just y} n ahl = ahl x y Code-is-hlevel {x = just x} {y = nothing} n ahl = hlevel (1 + n) Code-is-hlevel {x = nothing} {y = just x} n ahl = hlevel (1 + n) Code-is-hlevel {x = nothing} {y = nothing} n ahl = hlevel (1 + n)
Now that weβve characterised the path space, we can determine the
h-level of Maybe
.
Maybe-is-hlevel : (n : Nat) β is-hlevel A (2 + n) β is-hlevel (Maybe A) (2 + n) Maybe-is-hlevel n ahl x y = Equivβis-hlevel (1 + n) (MaybePath.PathβCode x y) (MaybePath.Code-is-hlevel n ahl)
instance H-Level-Maybe : β {β} {A : Type β} {n} β¦ _ : 2 β€ n β¦ β¦ _ : H-Level A n β¦ β H-Level (Maybe A) n H-Level-Maybe {n = suc (suc n)} β¦ sβ€s (sβ€s p) β¦ = hlevel-instance $ Maybe-is-hlevel n (hlevel (2 + n))
We also note that just
is an embedding; this
follows immediately from the characterisation of the path space.
just-cancellable : β {x y : A} β (just x β‘ just y) β (x β‘ y) just-cancellable {x = x} {y = y} = MaybePath.PathβCode (just x) (just y) just-is-embedding : is-embedding (just {A = A}) just-is-embedding = cancellableβembedding just-cancellable
This lets us show that Maybe
reflects h-levels.
Maybe-reflect-hlevel : (n : Nat) β is-hlevel (Maybe A) (2 + n) β is-hlevel A (2 + n) Maybe-reflect-hlevel n mhl = embeddingβis-hlevel {f = just} (1 + n) just-is-embedding mhl
Discretenessπ
If Maybe A
is discrete, then A
must also be
discrete. This follows from the fact that just
is
injective.
Maybe-reflect-discrete : Discrete (Maybe A) β Discrete A Maybe-reflect-discrete eq? = Discrete-inj just just-inj eq?
Misc. propertiesπ
If A
is empty, then a Maybe A
must be nothing
.
refute-just : Β¬ A β (x : Maybe A) β x β‘ nothing refute-just Β¬a (just a) = absurd (Β¬a a) refute-just Β¬a nothing = refl
As a corollary, if A
is empty, then Maybe A
is contractible.
emptyβmaybe-is-contr : Β¬ A β is-contr (Maybe A) emptyβmaybe-is-contr Β¬a .centre = nothing emptyβmaybe-is-contr Β¬a .paths x = sym $ refute-just Β¬a x
Next, note that map
is functorial.
map-id : β {β} {A : Type β} (x : Maybe A) β map id x β‘ x map-id (just x) = refl map-id nothing = refl map-β : β {β β' β''} {A : Type β} {B : Type β'} {C : Type β''} {f : B β C} {g : A β B} β (x : Maybe A) β map (f β g) x β‘ map f (map g x) map-β (just x) = refl map-β nothing = refl
Furthermore, <|>
is left and right unital,
associative, and is preserved by map
.
<|>-idl : β {A : Type β} β (x : Maybe A) β (nothing <|> x) β‘ x <|>-idl x = refl <|>-idr : β {A : Type β} β (x : Maybe A) β (x <|> nothing) β‘ x <|>-idr (just x) = refl <|>-idr nothing = refl <|>-assoc : β {A : Type β} β (x y z : Maybe A) β (x <|> (y <|> z)) β‘ ((x <|> y) <|> z) <|>-assoc (just x) y z = refl <|>-assoc nothing y z = refl map-<|> : β {A : Type β} {B : Type β'} {f : A β B} β (x y : Maybe A) β map f (x <|> y) β‘ (map f x <|> map f y) map-<|> (just x) y = refl map-<|> nothing y = refl
Injectivityπ
We can prove that the Maybe
type constructor,
considered as a function from a universe to itself, is injective.
Maybe-injective : Maybe A β Maybe B β A β B Maybe-injective e = IsoβEquiv (aβb , iso bβa (lemma e) il) where aβb = maybe-injective e bβa = maybe-injective (Equiv.inverse e) module _ (e : Maybe A β Maybe B) where abstract private module e = Equiv e module eβ»ΒΉ = Equiv e.inverse lemma : is-right-inverse (maybe-injective (Equiv.inverse e)) (maybe-injective e) lemma x with inspect (e.from (just x)) lemma x | just y , p with inspect (e.to (just y)) lemma x | just y , p | just z , q = just-inj (sym q β ap e.to (sym p) β e.Ξ΅ _) lemma x | just y , p | nothing , q with inspect (e.to nothing) lemma x | just y , p | nothing , q | nothing , r = absurd (justβ nothing (e.injectiveβ q r)) lemma x | just y , p | nothing , q | just z , r = absurd (nothingβ just (sym q β ap e.to (sym p) β e.Ξ΅ _)) lemma x | nothing , p with inspect (e.from nothing) lemma x | nothing , p | nothing , q = absurd (justβ nothing (eβ»ΒΉ.injectiveβ p q)) lemma x | nothing , p | just y , q with inspect (e.to (just y)) lemma x | nothing , p | just y , q | just z , r = absurd (justβ nothing (sym r β ap e.to (sym q) β e.Ξ΅ _)) lemma x | nothing , p | just y , q | nothing , r with inspect (e.to nothing) lemma x | nothing , p | just y , q | nothing , r | nothing , s = absurd (justβ nothing (e.injectiveβ r s)) lemma x | nothing , p | just y , q | nothing , r | just z , s = just-inj (sym s β ap e.to (sym p) β e.Ξ΅ _) abstract il : is-left-inverse bβa aβb il = p' where p : is-right-inverse (maybe-injective (Equiv.inverse (Equiv.inverse e))) (maybe-injective (Equiv.inverse e)) p = lemma (Equiv.inverse e) p' : is-right-inverse (maybe-injective e) (maybe-injective (Equiv.inverse e)) p' = subst (Ξ» e' β is-right-inverse (maybe-injective e') (maybe-injective (Equiv.inverse e))) {Equiv.inverse (Equiv.inverse e)} {e} trivial! p
Maybe-is-sum : Maybe A β (β€ β A) Maybe-is-sum {A = A} = IsoβEquiv (to , iso from ir il) where to : Maybe A β β€ β A to (just x) = inr x to nothing = inl tt from : β€ β A β Maybe A from (inr x) = just x from (inl _) = nothing ir : is-right-inverse from to ir (inl x) = refl ir (inr x) = refl il : is-right-inverse to from il nothing = refl il (just x) = refl