\import Algebra.Monoid
\import Function.Meta
\import Logic
\import Meta
\import Paths
\import Paths.Meta
\import Set
\record Partial (E : \Set) {
| isDefined : \Prop
| \coerce value : isDefined -> E
\func HasValue (a : E) => \Sigma (P : isDefined) (value P = a)
} \where {
\func make {X : \Set} (P : \Prop) (f : P -> X) => \new Partial X P f
}
\func defined {X : \Set} (x : X) : Partial X \cowith
| isDefined => \Sigma
| value _ => x
\func undefined {X : \Set} : Partial X \cowith
| isDefined => Empty
| value => \case __
\lemma partial-ext {X : \Set} {u v : Partial X} (d : u.isDefined <-> v.isDefined) (e : \Pi (p : u.isDefined) (q : v.isDefined) -> u (\box p) = v \box q) : u = v
=> exts (<->_=.1 d, \lam p => pmap u prop-pi *> e p (transport (\lam P => P) (<->_=.1 d) p) *> pmap v prop-pi)
\lemma partial-ext-left {X : \Set} {u v : Partial X} (d : u.isDefined <-> v.isDefined) (e : \Pi (p : u.isDefined) -> u p = v (d.1 p)) : u = v
=> partial-ext d \lam p _ => pmap u prop-pi *> e p *> pmap v prop-pi
\lemma partial-ext-right {X : \Set} {u v : Partial X} (d : u.isDefined <-> v.isDefined) (e : \Pi (p : v.isDefined) -> u (d.2 p) = v p) : u = v
=> partial-ext d \lam _ q => pmap u prop-pi *> e q *> pmap v prop-pi
\lemma defined-ext {X : \Set} {u : Partial X} {x : X} (d : u.isDefined) (p : u d = x) : u = defined x
=> partial-ext (\lam _ => (), \lam _ => d) \lam q q => pmap u prop-pi *> p
\where {
\protected \lemma isDefined (p : u = defined x) : u.isDefined
=> transportInv (\lam x => x.isDefined) p ()
\protected \lemma value (p : u = defined x) : u (isDefined p) = x
=> transportInv (\lam (v : Partial X) => \Pi (p : v.isDefined) -> v p = x) p (\lam _ => idp) (isDefined p)
}
\lemma undefined-ext {X : \Set} {u : Partial X} (d : Not u.isDefined) : u = undefined
=> partial-ext (d,absurd) \lam p => absurd (d p)
\lemma partial-defined {X : \Set} {u v : Partial X} (p : u = v) : u.isDefined <-> v.isDefined
=> <->_=.2 $ pmap (isDefined {__}) p
\lemma partial-value {X : \Set} {u v : Partial X} (p : u = v) {d : u.isDefined} {e : v.isDefined} : u d = v e
=> path \lam i => p i (prop-dpi _ d e i)
\lemma defined-inj {X : \Set} {x y : X} (p : defined x = {Partial X} defined y) : x = y
=> partial-value {X} p
\func plift {X Y : \Set} (f : X -> Y) (p : Partial X) : Partial Y \cowith
| isDefined => p.isDefined
| value d => f (p d)
\func plift2 {X Y Z : \Set} (f : X -> Y -> Z) (p : Partial X) (q : Partial Y) : Partial Z \cowith
| isDefined => \Sigma p.isDefined q.isDefined
| value d => f (p d.1) (q d.2)
\instance PartialAddMonoid (X : AddMonoid) : AddMonoid (Partial X)
| zro => defined X.zro
| + => plift2 (+)
| zro-left => partial-ext (__.2, ((),__)) \lam p q => zro-left
| zro-right => partial-ext (__.1, (__,())) \lam p q => zro-right
| +-assoc => partial-ext (\lam s => (s.1.1,(s.1.2,s.2)), \lam s => ((s.1,s.2.1),s.2.2)) \lam p q => +-assoc