# Partial function

A partial function from a set X to a set Y is a rule that assigns to each element of X at most one element of Y, but need not assign a value to every element of X; it is formally a function from some subset of X to Y, written f : X ⇀ Y<sup>[1](https://leanprover-community.github.io/logic_and_proof/functions.html)</sup>. Total functions, which assign exactly one value to every input, are the special case in which the subset is all of X<sup>[1](https://leanprover-community.github.io/logic_and_proof/functions.html)</sup>. Partial functions are central in computability theory, where undefined usually means nontermination.<sup>[2](https://tamnd.github.io/brain/maths/03/10.2/)</sup>

| Key fact | Detail |
|---|---|
| Definition | A partial function f : X ⇀ Y is a function from some subset A of X to Y; A is the domain of definition, and f(x) ↓ indicates f is defined at x<sup>[1](https://leanprover-community.github.io/logic_and_proof/functions.html)</sup> |
| Graph form | A partial function is a functional relation: for every x there is at most one y with (x, y) in the graph; total functions map each element to exactly one value<sup>[3](https://ai.dmi.unibas.ch/_files/teaching/hs22/dmics/slides/dmics-b08-handout.pdf)</sup> |
| Composition | g ∘ f is defined at x exactly when f is defined at x and g is defined at f(x); otherwise undefined<sup>[3](https://ai.dmi.unibas.ch/_files/teaching/hs22/dmics/slides/dmics-b08-handout.pdf)</sup> |
| Lifting | f : A ⇀ B becomes a total function A → B⊥ by adjoining an undefined element ⊥ and sending inputs outside the domain to it<sup>[4](https://ncatlab.org/nlab/show/partial%20map%20classifier)</sup> |
| Computability | Partial recursive functions are built by composition, primitive recursion, and minimization; minimization is the operation that introduces genuine partiality<sup>[5](https://www.cl.cam.ac.uk/teaching/1112/CompTheory/lectures/lecture-8.pdf)</sup> |
| Undefined = nontermination | In computability theory, f(x) undefined usually means the algorithm does not halt on input x<sup>[2](https://tamnd.github.io/brain/maths/03/10.2/)</sup> |
| Language support | Scala exposes PartialFunction with isDefinedAt; OCaml recommends 'a option or ('a, 'b) result for non-bug failures<sup>[6](https://www.scala-lang.org/api/current/scala/PartialFunction.html)</sup><sup> • </sup><sup>[7](https://github.com/ocaml/ocaml.org/blob/main/data/tutorials/guides/1wf_02_error_handling.md)</sup> |

## Definition and basic properties

A partial function f from a set A to a set B is given by a functional relation G over A and B, called the graph of f; f(x) is undefined when there is no y in B with (x, y) in G<sup>[3](https://ai.dmi.unibas.ch/_files/teaching/hs22/dmics/slides/dmics-b08-handout.pdf)</sup>. Equivalently, it consists of a subset D of A together with a total function from D to B<sup>[8](https://ncatlab.org/nlab/show/partial+function)</sup>. The set D is the domain of definition, and the notation f(x) ↓ says that f is defined at x<sup>[1](https://leanprover-community.github.io/logic_and_proof/functions.html)</sup>.

Two partial functions can be compared with a special equality: f(x) ≃ g(x) means that both are defined at x with the same value, or both are undefined at x<sup>[1](https://leanprover-community.github.io/logic_and_proof/functions.html)</sup>. A total function f : A → B is a partial function from A to B defined at every x in A; for total functions there is no difference between the domain and the domain of definition<sup>[3](https://ai.dmi.unibas.ch/_files/teaching/hs22/dmics/slides/dmics-b08-handout.pdf)</sup>.

Viewed as a relation, a partial function f can be represented by a relation R_f(x, y) in which each x is related to no more than a single y. A multifunction (multivalued function) instead allows at least one y for each x, and a partial multifunction, which allows zero or several values, is essentially nothing more than an arbitrary relation<sup>[1](https://leanprover-community.github.io/logic_and_proof/functions.html)</sup>.

## Why functions are partial

Partiality can arise from the underlying domain: division is a classic example, since division by zero is undefined mathematically<sup>[9](https://ericnormand.substack.com/p/total-functions-and-beyond)</sup>. It can also come from computation: in computability theory an undefined value usually represents nontermination, so f(x) = y means the algorithm halts on input x and outputs y, while f(x) undefined means it does not halt<sup>[2](https://tamnd.github.io/brain/maths/03/10.2/)</sup>. And it can come from definition itself: questions of definedness, in [Solomon Feferman](https://www.edgepedia.org/solomon-feferman)'s phrase, involve reasoning about expressions which may or may not have a value, and are ubiquitous in mathematics<sup>[10](https://math.stanford.edu/%7Efeferman/papers/definedness.pdf)</sup>.

Conventions differ between fields. In secondary-school mathematics, functions are often considered partial by default, requiring one to specify a total function otherwise; the modern category-theoretic and type-theoretic convention is the reverse, that a function must be total<sup>[8](https://ncatlab.org/nlab/show/partial+function)</sup>.

## Partial functions in computability theory

A partial function f is partial recursive if it can be built up in finitely many steps from the basic functions using the operations of composition, primitive recursion, and minimization<sup>[5](https://www.cl.cam.ac.uk/teaching/1112/CompTheory/lectures/lecture-8.pdf)</sup>. Minimization is where genuine partiality enters: applied to a total function, the µ-operator returns the least y such that f(x₁, …, xₙ, y) = 0 if such a y exists, and is undefined otherwise<sup>[11](https://builds.openlogicproject.org/content/computability/recursive-functions/partial-functions.pdf)</sup>. Bounded minimization, which searches only up to a fixed bound z and returns z + 1 on failure, keeps the operator total, and the class of primitive recursive functions is closed under it<sup>[12](https://encyclopediaofmath.org/wiki/Primitive_recursive_function)</sup>.

A partial function counts as computable when some algorithm yields the right result on every input where the function has a value, and diverges endlessly on every input where it does not.<sup>[2](https://tamnd.github.io/brain/maths/03/10.2/)</sup> A function that is partial recursive and also total is simply called recursive<sup>[13](https://www.cs.umd.edu/users/gasarch/papers/comput.pdf)</sup>, and the class of recursive functions has traditionally been taken, via Church's Thesis, to correspond to those functions that can be effectively computed by an algorithm<sup>[14](https://plato.stanford.edu/entries/recursive-functions/)</sup>.

The tie to the halting problem is direct. A set A is solvable, also called decidable or recursive, if there exists a total recursive function f with f(x) = 1 when x ∈ A and f(x) = 0 otherwise, and unsolvable otherwise<sup>[13](https://www.cs.umd.edu/users/gasarch/papers/comput.pdf)</sup>. The halting problem HALT = { e | φ_e(e) ↓ } is an example of an unsolvable problem stated in terms of partial recursive functions<sup>[13](https://www.cs.umd.edu/users/gasarch/papers/comput.pdf)</sup>. Verifying totality is in many cases difficult or impossible by algorithmic means, which is one of the main sources of undecidability phenomena in computability theory<sup>[2](https://tamnd.github.io/brain/maths/03/10.2/)</sup>.

## Composition, lifting, and making partiality explicit

The composition g ∘ f of partial functions f : A ⇀ B and g : B ⇀ C is defined at x exactly when f is defined for x and g is defined for f(x), and is undefined otherwise<sup>[3](https://ai.dmi.unibas.ch/_files/teaching/hs22/dmics/slides/dmics-b08-handout.pdf)</sup>. The restriction of a partial function to its domain of definition is a total function, and an extension f₀ of f satisfies A ⊆ A₀ and f₀|A = f<sup>[3](https://ai.dmi.unibas.ch/_files/teaching/hs22/dmics/slides/dmics-b08-handout.pdf)</sup>.

**Lifting to a total function.** The standard technique is to adjoin a new element ⊥, read as "undefined", to the codomain B and send every input outside the domain of definition to ⊥, turning f : A ⇀ B into a total function f̄ : A → B⊥<sup>[4](https://ncatlab.org/nlab/show/partial%20map%20classifier)</sup>. In programming this appears as the option type: OCaml's 'a option represents either data of type 'a, such as Some 42 as an int option, or the absence of data as None<sup>[7](https://github.com/ocaml/ocaml.org/blob/main/data/tutorials/guides/1wf_02_error_handling.md)</sup>. Isabelle's code generator uses the same device: a non-tail-recursive partial function can be rewritten to return an option type, where Some x represents the result x and None represents nontermination<sup>[15](https://isabelle.in.tum.de/website-Isabelle2026-RC0/dist/library/Doc/Codegen/Partial_Functions.html)</sup>.

Arbitrary total extensions have a cost. A partial function f : Nⁿ ⇀ N may be extended to a total function g by assigning arbitrary values to inputs where f is undefined, but such an extension may lose the computational meaning of the original function<sup>[2](https://tamnd.github.io/brain/maths/03/10.2/)</sup>.

## Partiality in category theory and domain theory

In a category with pullbacks, a partial map A ⇀ B is a span A ← D → B in which D → A is a monomorphism; the subobject D ↪ A is called the domain of the partial map<sup>[4](https://ncatlab.org/nlab/show/partial%20map%20classifier)</sup>. For sets this recovers the subset definition: a partial map is a total map from a subobject of the domain, the domain of definedness<sup>[16](https://strathprints.strath.ac.uk/60204/1/Chapman_etal_JFR2017_Formalizing_restriction_categories.pdf)</sup>.

The category of sets and partial functions can be made a category of total functions via the partial map classifier, which replaces each set S with S⊥, the set of subsets of S with at most one element; the resulting category is equivalent to, but not isomorphic with, the category of pointed sets<sup>[8](https://ncatlab.org/nlab/show/partial+function)</sup>. In Lean's Mathlib, PartialFun is the category of types equipped with partial functions, classically equivalent to the category of pointed types; the equivalence cannot hold constructively, because being defined for a Part is generally undecidable while being sent to Option.none is decidable<sup>[17](https://leanprover-community.github.io/mathlib4_docs/Mathlib/CategoryTheory/Category/PartialFun.html)</sup>.

**Restriction categories.** Cockett and Lack's restriction categories give an abstract axiomatic account of partiality, sound and complete with respect to partial map categories<sup>[16](https://strathprints.strath.ac.uk/60204/1/Chapman_etal_JFR2017_Formalizing_restriction_categories.pdf)</sup>. A restriction structure assigns to each map f : A → B an idempotent f̄ : A → A satisfying axioms such as ff̄ = f, measuring the degree of partiality of the arrow; in the basic example of sets and partial functions, f̄(x) is x whenever f is defined and is undefined otherwise<sup>[18](https://pages.cpsc.ucalgary.ca/%7Erobin/FMCS/FMCS_06/RestrictionsI.pdf)</sup>. A significant motivation behind the study of partial maps is the study of categories of partial recursive functions<sup>[18](https://pages.cpsc.ucalgary.ca/%7Erobin/FMCS/FMCS_06/RestrictionsI.pdf)</sup>.

On the logical side, the basic logic of partial terms (BPT) extends to separate logics for call-by-value and call-by-name evaluation of simply typed lambda-terms with pairs, projections, if-then-else, and least fixed point recursion, with adequacy shown via denotational semantics; notably, neither the programs nor the logics contain the constant "undefined"<sup>[19](https://www.cambridge.org/core/journals/journal-of-functional-programming/article/why-the-constant-undefined-logics-of-partial-terms-for-strict-and-nonstrict-functional-programming-languages/3351BE72FC143DEEC339C155D7910A0B)</sup>. Feferman's survey of definedness runs from a general logic of partial terms through partial combinatory and lambda calculi to an expressively rich theory of partial functions in computational contexts<sup>[10](https://math.stanford.edu/%7Efeferman/papers/definedness.pdf)</sup>. In program verification, the Logic of Partial Functions (LPF) tackles undefinedness at its root by using a weaker logic, argued to fit a "posit and prove" style of development<sup>[20](https://www.sciencedirect.com/science/article/pii/S1571066105052473)</sup>.

## Partial functions in programming

Languages represent partiality in several ways, each with a different safety profile.

**Explicit domain predicates.** Scala's standard library provides PartialFunction[A, B], a unary function whose domain does not necessarily include all values of type A, with isDefinedAt to test dynamically whether a value is in the domain<sup>[6](https://www.scala-lang.org/api/current/scala/PartialFunction.html)</sup>. The contract is weaker than it looks: even if isDefinedAt returns true for a value, calling apply on it may still throw an exception, for example { case x => x / 0 } throws ArithmeticException: / by zero, so the caller is responsible for checking isDefinedAt first<sup>[6](https://www.scala-lang.org/api/current/scala/PartialFunction.html)</sup>. The documentation recommends applyOrElse as the usual way to respect the contract, since it is expected to be more efficient than calling isDefinedAt and apply separately<sup>[6](https://www.scala-lang.org/api/current/scala/PartialFunction.html)</sup>.

**Option and result types.** In OCaml it is considered good practice for functions that can fail in non-bug cases, such as network failures or missing keys, to return 'a option or ('a, 'b) result rather than throwing an exception<sup>[7](https://github.com/ocaml/ocaml.org/blob/main/data/tutorials/guides/1wf_02_error_handling.md)</sup>.

**Sentinel values.** In JavaScript and [TypeScript](https://www.edgepedia.org/typescript), division by zero silently returns NaN, Infinity, or -Infinity, which propagate into other arithmetic operations; throwing an exception on divide-by-zero makes the function partial but protects code from these values<sup>[9](https://ericnormand.substack.com/p/total-functions-and-beyond)</sup>.

In Isabelle/[HOL](https://www.edgepedia.org/higher-order-logic), every function is total: applying f to x always yields the value f x, and undefinedness as a concept does not exist. Partial functions are therefore modeled as total functions with an additional domain predicate characterizing the inputs where the function terminates<sup>[21](https://isabelle.in.tum.de/website-Isabelle2026-RC0/dist/Isabelle2026-RC0/doc/functions.pdf)</sup>. The function package derives simplification and induction rules guarded by domain conditions, called psimps and pinduct<sup>[21](https://isabelle.in.tum.de/website-Isabelle2026-RC0/dist/Isabelle2026-RC0/doc/functions.pdf)</sup>.

## Recent developments

The main recent development is in proof assistants. Lean 4.17.0, released 2025-03-03, shipped the Partial Fixpoint feature (PR #6355), which adds the ability to define possibly non-terminating functions and still reason about them equationally, as long as they are tail-recursive or operate within certain monads such as Option<sup>[22](https://lean-lang.org/doc/reference/latest/releases/v4.17.0/)</sup>. The feature was heavily inspired by Isabelle's partial_function command<sup>[23](https://github.com/leanprover/lean4/pull/6355)</sup>, and it brings a fragment of domain theory into the proof assistant, up to a variant of the Knaster–Tarski theorem, together with a monotonicity tactic, a derecursifier supporting dependent and mutual recursion, and fixed-point induction principles<sup>[23](https://github.com/leanprover/lean4/pull/6355)</sup>.

The two systems now represent the two established alternatives: Isabelle's psimps and pinduct rules guard equational reasoning with domain conditions<sup>[21](https://isabelle.in.tum.de/website-Isabelle2026-RC0/dist/Isabelle2026-RC0/doc/functions.pdf)</sup>, while Lean's partial_fixpoint instead supports equational reasoning for a restricted class of partial definitions by constructing least fixed points<sup>[23](https://github.com/leanprover/lean4/pull/6355)</sup>.

## References

1. [15. Functions, Logic and Proof 3.18.4, LeanProver Community](https://leanprover-community.github.io/logic_and_proof/functions.html)
2. [10.2 Partial vs Total Functions, brain (tamnd)](https://tamnd.github.io/brain/maths/03/10.2/)
3. [Discrete Mathematics in Computer Science, Functions, University of Basel lecture notes](https://ai.dmi.unibas.ch/_files/teaching/hs22/dmics/slides/dmics-b08-handout.pdf)
4. [partial map classifier, nLab](https://ncatlab.org/nlab/show/partial%20map%20classifier)
5. [Partial Recursive Functions, University of Cambridge Computer Laboratory lecture 8](https://www.cl.cam.ac.uk/teaching/1112/CompTheory/lectures/lecture-8.pdf)
6. [scala.PartialFunction, Scala API documentation](https://www.scala-lang.org/api/current/scala/PartialFunction.html)
7. [Error handling, OCaml tutorial (ocaml.org)](https://github.com/ocaml/ocaml.org/blob/main/data/tutorials/guides/1wf_02_error_handling.md)
8. [partial function, nLab](https://ncatlab.org/nlab/show/partial+function)
9. [Total functions and beyond, Eric Normand's Newsletter](https://ericnormand.substack.com/p/total-functions-and-beyond)
10. [Solomon Feferman, Definedness](https://math.stanford.edu/%7Efeferman/papers/definedness.pdf)
11. [rec.1 Partial Recursive Functions, Open Logic Project](https://builds.openlogicproject.org/content/computability/recursive-functions/partial-functions.pdf)
12. [Primitive recursive function, Encyclopedia of Mathematics](https://encyclopediaofmath.org/wiki/Primitive_recursive_function)
13. [Recursive Functions and the Church-Turing Thesis, University of Maryland course notes (Gasarch)](https://www.cs.umd.edu/users/gasarch/papers/comput.pdf)
14. [Recursive Functions, Stanford Encyclopedia of Philosophy](https://plato.stanford.edu/entries/recursive-functions/)
15. [Theory Partial_Functions, Isabelle Codegen documentation](https://isabelle.in.tum.de/website-Isabelle2026-RC0/dist/library/Doc/Codegen/Partial_Functions.html)
16. [Formalizing Restriction Categories, Chapman et al., Journal of Formalized Reasoning (2017)](https://strathprints.strath.ac.uk/60204/1/Chapman_etal_JFR2017_Formalizing_restriction_categories.pdf)
17. [Mathlib.CategoryTheory.Category.PartialFun, Mathlib4 documentation](https://leanprover-community.github.io/mathlib4_docs/Mathlib/CategoryTheory/Category/PartialFun.html)
18. [Restrictions, Cockett & Lack, Theoretical Computer Science](https://pages.cpsc.ucalgary.ca/%7Erobin/FMCS/FMCS_06/RestrictionsI.pdf)
19. [Why the constant 'undefined'? Logics of partial terms, Journal of Functional Programming](https://www.cambridge.org/core/journals/journal-of-functional-programming/article/why-the-constant-undefined-logics-of-partial-terms-for-strict-and-nonstrict-functional-programming-languages/3351BE72FC143DEEC339C155D7910A0B)
20. [Reasoning About Partial Functions in the Formal Development of Programs, ScienceDirect](https://www.sciencedirect.com/science/article/pii/S1571066105052473)
21. [Defining Recursive Functions in Isabelle/HOL, §8 Partiality](https://isabelle.in.tum.de/website-Isabelle2026-RC0/dist/Isabelle2026-RC0/doc/functions.pdf)
22. [Lean 4.17.0 release notes (2025-03-03)](https://lean-lang.org/doc/reference/latest/releases/v4.17.0/)
23. [feat: partial_fixpoint: partial functions with equations, Lean 4 PR #6355](https://github.com/leanprover/lean4/pull/6355)

---
*Topic: Encyclopedia › Physical world and mathematics › Mathematics and statistics › Logic and discrete mathematics › General discrete mathematics and discrete structures › Discrete mathematics*

*Initially written Sep 17, 2026 · Reviewed: Sep 30, 2026; Oct 15, 2026 · Edited: Sep 30, 2026; Oct 15, 2026 · Last review: Oct 15, 2026*

*Copyright 2026 EdgeChat AI, a subsidiary of Biostate AI.*

License: Edgepedia Community License 1.0, https://www.edgepedia.org/edgepedia/license
