Suppose I have a set A ⊆ nat
. I want to model in Isabelle a function f : A ⇒ Y
. I could use either:
- a partial function, i.e. one of type
nat ⇒ Y option
, or - a total function, i.e. one of type
nat ⇒ Y
that is unspecified for inputs not inA
.
I wonder which is the 'better' option. I see a couple of factors:
The "partial function" approach is better because it is easier to compare partial functions for equality. That is, if I want to see if
f
is equal to another function,g : A ⇒ Y
, then I just sayf = g
. To compare under-specified total functionsf
andg
, I would have to say∀x ∈ A. f x = g x
.The "under-specified total function" approach is better because I don't have to faff with the constructing/deconstructing
option
types all the time. For instance, iff
is an under-specified total function, andx ∈ A
, then I can just sayf x
, but iff
is a partial function I would have to say(the ∘ f) x
. For another instance, it's trickier to do function composition on partial functions than on total functions.
For a concrete instance relevant to this question, consider the following attempt at formalising simple graphs.
type_synonym node = nat
record 'a graph =
V :: "node set"
E :: "(node × node) set"
label :: "node ⇒ 'a"
A graph comprises a set of nodes, an edge relation between them, and a label
for each node. We only care about the label of nodes that are in V
. So, should label
be a partial function node ⇒ 'a option
with dom label = V
, or should it just be a total function that is unspecified outside of V
?