Partial functions #
This file defines partial functions. Partial functions are like functions, except they can also be
"undefined" on some inputs. We define them as functions α → part β.
Definitions #
pfun α β: Type of partial functions fromαtoβ. Defined asα → part βand denotedα →. β.pfun.dom: Domain of a partial function. Set of values on which it is defined. Not to be confused with the domain of a functionα → β, which is a type (αpresently).pfun.fn: Evaluation of a partial function. Takes in an element and a proof it belongs to the partial function'sdom.pfun.as_subtype: Returns a partial function as a function from itsdom.pfun.to_subtype: Restricts the codomain of a function to a subtype.pfun.eval_opt: Returns a partial function with a decidabledomas a functiona → option β.pfun.lift: Turns a function into a partial function.pfun.id: The identity as a partial function.pfun.comp: Composition of partial functions.pfun.restrict: Restriction of a partial function to a smallerdom.pfun.res: Turns a function into a partial function with a prescribed domain.pfun.fix: First return map of a partial functionf : α →. β ⊕ α.pfun.fix_induction: A recursion principle forpfun.fix.
Partial functions as relations #
Partial functions can be considered as relations, so we specialize some rel definitions to pfun:
pfun.image: Image of a set under a partial function.pfun.ran: Range of a partial function.pfun.preimage: Preimage of a set under a partial function.pfun.core: Core of a set under a partial function.pfun.graph: Graph of a partial functiona →. βas aset (α × β).pfun.graph': Graph of a partial functiona →. βas arel α β.
pfun α as a monad #
Monad operations:
Equations
- pfun.inhabited = {default := λ (a : α), part.none}
Turns a partial function into a function out of its domain.
Equations
- f.as_subtype s = f.fn ↑s _
The type of partial functions α →. β is equivalent to
the type of pairs (p : α → Prop, f : subtype p → β).
Equations
- pfun.has_coe = {coe := pfun.lift β}
Equations
First return map. Transforms a partial function f : α →. β ⊕ α into the partial function
α →. β which sends a : α to the first value in β it hits by iterating f, if such a value
exists. By abusing notation to illustrate, either f a is in the β part of β ⊕ α (in which
case f.fix a returns f a), or it is undefined (in which case f.fix a is undefined as well), or
it is in the α part of β ⊕ α (in which case we repeat the procedure, so f.fix a will return
f.fix (f a)).
Equations
- f.fix = λ (a : α), part.assert (acc (λ (x y : α), sum.inr x ∈ f y) a) (λ (h : acc (λ (x y : α), sum.inr x ∈ f y) a), well_founded.fix_F (λ (a : α) (IH : Π (y : α), (λ (x y : α), sum.inr x ∈ f y) y a → part β), part.assert (f a).dom (λ (hf : (f a).dom), (λ (_x : β ⊕ α) (e : (f a).get hf = _x), _x.cases_on (λ (b : β) (e : (f a).get hf = sum.inl b), part.some b) (λ (a' : α) (e : (f a).get hf = sum.inr a'), IH a' _) e) ((f a).get hf) _)) a h)
A recursion principle for pfun.fix.
Equations
- pfun.fix_induction h H = acc.drec (λ (a : α) (ha : ∀ (y : α), (λ (x y : α), sum.inr x ∈ f y) y a → acc (λ (x y : α), sum.inr x ∈ f y) y) (IH : Π (y : α) (ᾰ : (λ (x y : α), sum.inr x ∈ f y) y a), (λ {a : α} (_x : acc (λ (x y : α), sum.inr x ∈ f y) a), (∃ (h : acc (λ (x y : α), sum.inr x ∈ f y) a), b ∈ well_founded.fix_F (λ (a : α) (IH : Π (y : α), (λ (x y : α), sum.inr x ∈ f y) y a → part β), part.assert (f a).dom (λ (hf : (f a).dom), (λ (_x : β ⊕ α) (e : (f a).get hf = _x), _x.cases_on (λ (b : β) (e : (f a).get hf = sum.inl b), part.some b) (λ (a' : α) (e : (f a).get hf = sum.inr a'), IH a' _) e) ((f a).get hf) _)) a h) → b ∈ well_founded.fix_F (λ (a : α) (IH : Π (y : α), (λ (x y : α), sum.inr x ∈ f y) y a → part β), part.assert (f a).dom (λ (hf : (f a).dom), (λ (_x : β ⊕ α) (e : (f a).get hf = _x), _x.cases_on (λ (b : β) (e : (f a).get hf = sum.inl b), part.some b) (λ (a' : α) (e : (f a).get hf = sum.inr a'), IH a' _) e) ((f a).get hf) _)) a _x → C a) _) (h : ∃ (h : acc (λ (x y : α), sum.inr x ∈ f y) a), b ∈ well_founded.fix_F (λ (a : α) (IH : Π (y : α), (λ (x y : α), sum.inr x ∈ f y) y a → part β), part.assert (f a).dom (λ (hf : (f a).dom), (λ (_x : β ⊕ α) (e : (f a).get hf = _x), _x.cases_on (λ (b : β) (e : (f a).get hf = sum.inl b), part.some b) (λ (a' : α) (e : (f a).get hf = sum.inr a'), IH a' _) e) ((f a).get hf) _)) a h) (h₂ : b ∈ well_founded.fix_F (λ (a : α) (IH : Π (y : α), (λ (x y : α), sum.inr x ∈ f y) y a → part β), part.assert (f a).dom (λ (hf : (f a).dom), (λ (_x : β ⊕ α) (e : (f a).get hf = _x), _x.cases_on (λ (b : β) (e : (f a).get hf = sum.inl b), part.some b) (λ (a' : α) (e : (f a).get hf = sum.inr a'), IH a' _) e) ((f a).get hf) _)) a _), H a _ (λ (a'' : α) (fa'' : sum.inr a'' ∈ f a), IH a'' fa'' _ _)) _ _ _
Another induction lemma for b ∈ f.fix a which allows one to prove a predicate P holds for
a given that f a inherits P from a and P holds for preimages of b.
Equations
- f.fix_induction' b h hbase hind = pfun.fix_induction h (λ (a' : α) (h : b ∈ f.fix a') (ih : Π (a'' : α), sum.inr a'' ∈ f a' → C a''), (λ (_x : β ⊕ α) (e : (f a').get _ = _x), _x.cases_on (λ (b' : β) (e : (f a').get _ = sum.inl b'), hbase a' _) (λ (a'' : α) (e : (f a').get _ = sum.inr a''), hind a' a'' _ _ (ih a'' _)) e) ((f a').get _) _)
Turns a function into a partial function to a subtype.
Equations
- pfun.to_subtype p f = λ (a : α), {dom := p (f a), get := subtype.mk (f a)}