# Partiality

How can we model partial or non-terminating computations?

```
{-# OPTIONS --cubical-compatible --allow-unsolved-metas #-}
module _ where
private
  variable
    A B C : Set
```

## Maybe
```
open import Data.Bool as B using (Bool; true; false; _∨_; _≟_)
open import Data.Unit
open import Data.Sum
open import Data.Maybe as Maybe renaming (_>>=_ to Maybe-bind)
open import Data.Nat
open import Data.Product
open import Data.List
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary using (Dec; yes; no; dec⇒maybe)
open import Function.Base

_⇀_ : Set → Set → Set
A ⇀ B = A → Maybe B

Maybe′ : Set → Set
Maybe′ B = ⊤ ⊎ B
Maybe′′ : Set → Set
Maybe′′ B = Σ[ l ∈ List B ] length l ≤ 1

-- index ₘ = Maybe

_∘ₘ_ :  (B ⇀ C) → (A ⇀ B) → (A ⇀ C)
g ∘ₘ f = λ a → case (f a) of λ
  { (just b) → g b
  ; nothing → nothing
  }

Is-definedₘ : (A ⇀ B) → A → Set
Is-definedₘ f = (Is-just ∘ f)
  -- Σ[ a ∈ A ] ∃[ b ] f a ≡ just b
```
However, being defined is a decidable predicate on `A`, so we need a different description
of partiality for modelling non-termination:
## Spans
```
module version1 where
  record _⊇⟶_ (A B : Set) : Set₁ where
    field
      Is-defined : A → Set
      app : Σ A Is-defined → B

  guess : ∀ (B : Set) → ⊤ ⊇⟶ B
  guess B = record
    { Is-defined = λ _ → B
    ; app = λ { (_ , b) → b }
    }

record _⊇⟶_ (A B : Set) : Set₁ where
  field
    Is-defined : A → Set
    app : Σ A Is-defined → B
    well-defined : ∀ {x} {y} → proj₁ x ≡ proj₁ y
                             → app x ≡ app y
from-Maybe : (A ⇀ B) → (A ⊇⟶ B)
from-Maybe {A = A} {B = B} f =
  record
  { Is-defined = Is-definedₘ f
  ; app = app
    -- alternatively: λ { (x , just-b) → to-witness just-b }
  ; well-defined = well-defined
  }
  where
    app : Σ A (Is-definedₘ f) → B
    app (a , def-a) with (f a)
    ... | just b = b

    well-defined : {x y : Σ A (Is-definedₘ f)} →
                   proj₁ x ≡ proj₁ y → app x ≡ app y
    well-defined {(x , _)} {(_ , _)} refl with (f x)
    ... | just x₁ = refl

_∘ₚ_ : (B ⊇⟶ C) → (A ⊇⟶ B)  → (A ⊇⟶ C)
_∘ₚ_ {A = A} g f = record
  { Is-defined = Is-defined
  ; app = λ { (a , f[a]↓ , g[f[a]]↓) → g.app (f.app (a , f[a]↓) , g[f[a]]↓) }
  ; well-defined = g.well-defined ∘ f.well-defined
  }
  where
    module f = _⊇⟶_ f
    module g = _⊇⟶_ g
    Is-defined : A → Set
    Is-defined a = Σ[ f[a]↓ ∈ (f.Is-defined a) ]
                 g.Is-defined (f.app (a , f[a]↓))
```
[End of lecture on 6 July 2026]

## Step-Indexing
```
is-mono : (ℕ → Maybe A) → Set
is-mono f = ∀ n → Is-just (f n) → f (suc n) ≡ f n

record Step-Indexed (A : Set) : Set where
  field
    f : ℕ → Maybe A
    f-mono :  is-mono f

_⊑ₘ_ : Maybe A → Maybe A → Set
x ⊑ₘ y = Is-just x → x ≡ y

monotone : (ℕ → Maybe A) → Set
monotone f = ∀ m n → m ≤ n → f m ⊑ₘ f n

contains-true? : (s s' : ℕ → Bool) → Step-Indexed (∃[ k ] s k ≡ s' k)
contains-true? s s' = record
  { f = f
  ; f-mono = f-mono
  }
  where
    f : ℕ → Maybe (∃[ k ] s k ≡ s' k)
    f zero = nothing
    f (suc k) =
      (f k) <∣> Maybe.map (k ,_) (dec⇒maybe (s k B.≟ s' k)) 
    f-mono : is-mono f
    f-mono n Is-just[f[n]] with (f n)
    ... | just (k , sk≡s'k) = refl


```
The results on `Streams` and `Delay` were moved to [Delay.html](`Delay.lagda.md`).
[End of lecture on 9 July 2026]

## Additional lemmas

```
open import Data.Maybe.Relation.Unary.Any using (just)
open import Data.Maybe.Properties using (just-injective)
open import Data.Nat.Properties using (≤⇒≤′; m≤m⊔n; m≤n⊔m)
open import Data.Maybe.Relation.Unary.Any using (Any; just)


⊑ₘ-trans : ∀ { x y z : Maybe A } →  x ⊑ₘ y → y ⊑ₘ z → x ⊑ₘ z
⊑ₘ-trans {x = just x} x⊑ₘy y⊑ₘz x-is-just with (x⊑ₘy x-is-just)
... | refl = y⊑ₘz x-is-just

monotone′ : (ℕ → Maybe A) → Set
monotone′ f = ∀ {m} {n} → m ≤′ n → f m ⊑ₘ f n

is-mono⇒monotone′ : ∀ {f : ℕ → Maybe A} → is-mono f → monotone′ f
is-mono⇒monotone′ f-mono (≤′-reflexive refl) f-m-just = refl
is-mono⇒monotone′ f-mono {n = suc n} (≤′-step m≤n) f-m-just =
  ⊑ₘ-trans (is-mono⇒monotone′ f-mono m≤n) (sym ∘ f-mono n) f-m-just

is-mono⇒monotone : ∀ {f : ℕ → Maybe A} → is-mono f → monotone f
is-mono⇒monotone f-mono m n = is-mono⇒monotone′ f-mono ∘ ≤⇒≤′

module do-Step-Indexed where
  _>>=_ : Step-Indexed A → (A → Step-Indexed B) → Step-Indexed B
  _>>=_ {B = B} stepA g = record
    { f = f
    ; f-mono = f-mono
    }
    where
      module stepA = Step-Indexed stepA
      f : ℕ → Maybe B
      f k = Maybe-bind (stepA.f k) (λ a → Step-Indexed.f (g a) k)

      f-mono : is-mono f
      f-mono n Is-just[f[n]] with stepA.f n | stepA.f-mono n
      ... | just a | mono-n rewrite mono-n (just tt) =
        Step-Indexed.f-mono (g a) n Is-just[f[n]]

  return : A → Step-Indexed A
  return a = record
    { f = λ _ → just a
    ; f-mono = λ n x → refl
    }

  stepped-pair : Step-Indexed A
                 → Step-Indexed B
                 → Step-Indexed (A × B)
  stepped-pair {A = A} stepA stepB = do
    a ← stepA
    b ← stepB
    return (a , b)

mono⇒functional : ∀ {f : ℕ → Maybe A} → is-mono f
                  → ∀ {m} {v} → f m ≡ just v
                  → ∀ {n} {w} → f n ≡ just w
                  → v ≡ w
mono⇒functional {f = f} f-mono {m} {v} f[m]↓ {n} {w} f[n]↓ =
  just-injective (begin
    just v     ≡⟨ f[m]↓ ⟨
    f m        ≡⟨ f-monotone _ _ (m≤m⊔n m n) (subst Is-just (sym f[m]↓) (just tt)) ⟩
    f (m ⊔ n)  ≡⟨ f-monotone _ _ (m≤n⊔m m n) (subst Is-just (sym f[n]↓) (just tt)) ⟨
    f n        ≡⟨ f[n]↓ ⟩
    just w     ∎)
  where
    open ≡-Reasoning
    f-monotone : monotone f
    f-monotone _ _ = is-mono⇒monotone′ f-mono ∘ ≤⇒≤′

Step-Indexed-functional : {M₁ M₂ : Step-Indexed B}
                          {m n : ℕ} {v : B} {w : B}
                        → M₁ ≡ M₂
                        → Step-Indexed.f M₁ m ≡ just v
                        → Step-Indexed.f M₂ n ≡ just w
                        → v ≡ w
Step-Indexed-functional {M₁ = M} refl eq1 eq2 =
  mono⇒functional (Step-Indexed.f-mono M) eq1 eq2
```
