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 decidabledom
as 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)}