0% found this document useful (0 votes)
4 views12 pages

Fast Loose

The document discusses the concept of 'fast and loose reasoning' in functional programming, particularly in the context of total and partial languages. It argues that while certain equational laws may not hold in partial languages, the reasoning used by functional programmers is often still 'morally correct' under specific conditions. The paper aims to justify the informal reasoning practices of programmers and explores the implications of using partial equivalence relations in program verification.

Uploaded by

bezbra
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views12 pages

Fast Loose

The document discusses the concept of 'fast and loose reasoning' in functional programming, particularly in the context of total and partial languages. It argues that while certain equational laws may not hold in partial languages, the reasoning used by functional programmers is often still 'morally correct' under specific conditions. The paper aims to justify the informal reasoning practices of programmers and explores the implications of using partial equivalence relations in program verification.

Uploaded by

bezbra
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

Fast and Loose Reasoning is Morally Correct ∗

Nils Anders Danielsson John Hughes Jeremy Gibbons


Patrik Jansson Oxford University Computing Laboratory
Chalmers University of Technology [email protected]
{nad,rjmh,patrikj}@cs.chalmers.se

Abstract (fst x, snd x) = x, and (2)


Functional programmers often reason about programs as if fst (x, y) = x, (3)
they were written in a total language, expecting the results
to carry over to non-total (partial) languages. We justify and many others inspired by category theory. Such laws
such reasoning. can be used to perform very pleasant proofs of program
Two languages are defined, one total and one partial, equality, and are indeed the foundation of an entire school
with identical syntax. The semantics of the partial language of program transformation and derivation, the Squiggolers
includes partial and infinite values, and all types are lifted, [BdM96, Jeu90, BdBH+ 91, MFP91]. There is just one prob-
including the function spaces. A partial equivalence relation lem. In current real programming languages such as Haskell
(PER) is then defined, the domain of which is the total [PJ03] and ML [MTHM97], they are not generally valid.
subset of the partial language. For types not containing The reason these laws fail is the presence of the undefined
function spaces the PER relates equal values, and functions value ⊥, and the fact that, in Haskell, ⊥, λx.⊥ and (⊥, ⊥)
are related if they map related values to related values. are all different (violating the first two laws above), while in
It is proved that if two closed terms have the same ML, ⊥, (x, ⊥) and (⊥, y) are always the same (violating the
semantics in the total language, then they have related third).
semantics in the partial language. It is also shown that the The fact that these laws are invalid does not prevent
PER gives rise to a bicartesian closed category which can be functional programmers from using them when developing
used to reason about values in the domain of the relation. programs, whether formally or informally. Squiggolers hap-
pily derive programs from specifications using them, and
Categories and Subject Descriptors F.3.1 [Logics and then transcribe the programs into Haskell in order to run
Meanings of Programs]: Specifying and Verifying and Rea- them, confident that the programs will correctly implement
soning about Programs; D.3.2 [Programming Languages]: the specification. Countless functional programmers happily
Language Classifications—Applicative (functional) lan- curry or uncurry functions, confident that at worst they are
guages changing definedness a little in obscure cases. Yet is this
General Terms Languages, theory, verification confidence justified? Reckless use of invalid laws can lead
to patently absurd conclusions: for example, in ML, since
Keywords Equational reasoning, partial and total lan- (x, ⊥) = (y, ⊥) for any x and y, we can use the third law
guages, non-strict and strict languages, partial and infinite above to conclude that x = y, for any x and y. How do we
values, lifted types, inductive and coinductive types know that, when transforming programs using laws of this
sort, we do not, for example, transform a correctly termi-
1. Introduction nating program into an infinitely looping one?
This is the question we address in this paper. We call the
It is often claimed that functional programs are much easier
unjustified reasoning with laws of this sort “fast and loose”,
to reason about than their imperative counterparts. Func-
and we show, under some mild and unsurprising conditions,
tional languages satisfy many pleasing equational laws, such
that its conclusions are “morally correct”. In particular,
as
it is impossible to transform a terminating program into
curry ◦ uncurry = id , (1) a looping one. Our results justify the hand reasoning that
functional programmers already perform, and can be applied
∗ This work is partially funded by the Swedish Foundation for in proof checkers and automated provers to justify ignoring
Strategic Research as part of the research programme “Cover — ⊥-cases much of the time.
Combining Verification Methods in Software Development,” and In the next section we give an example showing how it
by the Royal Swedish Academy of Sciences’ funds. can be burdensome to keep track of all preconditions when
one is only interested in finite and total values, but is rea-
soning about a program written in a partial language. Sec-
Permission to make digital or hard copies of all or part of this work for tion 3 is devoted to defining the language that we focus
personal or classroom use is granted without fee provided that copies on, its syntax and two different semantics: one set-theoretic
are not made or distributed for profit or commercial advantage and
that copies bear this notice and the full citation on the first page. To
and one domain-theoretic. Section 4 briefly discusses par-
copy otherwise, to republish, to post on servers or to redistribute to tial equivalence relations (PERs), and Section 5 introduces
lists, requires prior specific permission and/or a fee. a PER on the domain-theoretic semantics. This PER is used
POPL’06 January 11–13, 2006, Charleston, South Carolina, USA. to model totality. In Section 6 a partial surjective homomor-
Copyright c 2006 ACM 1-59593-027-2/06/0001. . . $5.00. phism from the set-theoretic semantics to the quotient of the
domain-theoretic semantics given by the PER is exhibited, to the point, both lemmas (4) and (5) fail, and they fail due
and in Section 7 we use this homomorphism to prove our to both properly partial values, since
main result: fast and loose reasoning is morally correct. Sec- (Succ Zero + Succ ⊥) − Succ Zero = ⊥ = 6 Succ ⊥ and (9)
tion 8 provides a more abstract result, showing how the PER
gives rise to a category with many nice properties which reverse (reverse (Zero : ⊥)) = ⊥ =6 Zero : ⊥, (10)
can be used to reason about programs. We go back to our and infinite values, since
earlier example and show how it fits in with the theory in
Section 9. We also exhibit another example where reasoning (fix Succ + Zero) − fix Succ = ⊥ =
6 Zero and (11)
directly about the domain-theoretic semantics of a program reverse (reverse (repeat Zero)) = ⊥ =6 repeat Zero. (12)
may be preferable (Section 10). Section 11 recasts the the-
(Here fix is the fixpoint combinator, i.e. fix Succ is the
ory for a strict language, Section 12 discusses related work,
“infinite” lazy natural number. The application repeat x
and Section 13 concludes with a discussion of the results and
yields an infinite list containing only x.) Note that id ◦f = f
possible future extensions of the theory.
also fails, since we have lifted function spaces and id ◦ ⊥ =
Most proofs needed for the development below are only
λx.⊥ 6= ⊥, but that does not affect this example since
sketched; full proofs are available from Danielsson’s web
reverse 6= ⊥.
page [Dan05].
These problems are not surprising; they are the price you
pay for partiality. Values that are properly partial and/or in-
2. Propagating preconditions finite have different properties than their total, finite coun-
Let us begin with an example. Say that we need to prove terparts. A reasonable solution is to stay in the partial lan-
that the function map (λx.y + x) ◦ reverse :: [Nat] → [Nat] guage but restrict our inputs to total, finite values.
has a left inverse reverse ◦ map (λx.x − y). (All code in Let us see what the proof looks like then. We have to η-
this section uses Haskell-like syntax.) In a total language we expand our property, and assume that xs :: [Nat] is a total,
would do it more or less like this: finite list and that y :: Nat is a total, finite natural number.
(Note the terminology used here: if a list is said to be total,
(reverse ◦ map (λx.x − y)) ◦ (map (λx.y + x) ◦ reverse) then all elements in the list are assumed to be total as well,
= {map f ◦ map g = map (f ◦ g), ◦ associative} and similarly for finite values. The concepts of totality and
reverse ◦ map ((λx.x − y) ◦ (λx.y + x)) ◦ reverse finiteness are discussed in more detail in Sections 5 and 9,
respectively.) We get
= {(λx.x − y) ◦ (λx.y + x) = id }
((reverse ◦ map (λx.x − y))
reverse ◦ map id ◦ reverse
◦ (map (λx.y + x) ◦ reverse)) xs
= {map id = id }
= {map f ◦ map g = map (f ◦ g), definition of ◦}
reverse ◦ id ◦ reverse
reverse (map ((λx.x − y) ◦ (λx.y + x)) (reverse xs))
= {id ◦ f = f , ◦ associative}
• map f xs = map g xs if xs is total and f x = g x>
8 9
reverse ◦ reverse
>
< for all total x,
> >
=
= {reverse ◦ reverse = id} = • reverse xs is total, finite if xs is,
: • ((λx.x − y) ◦ (λx.y + x)) x = id x for total x and>
>
> >
id .
;
total, finite y
Note the lemmas used for the proof, especially reverse (map id (reverse xs))
(λx.x − y) ◦ (λx.y + x) = id , and (4) = {map id = id }
reverse ◦ reverse = id . (5) reverse (id (reverse xs))
Consider now the task of repeating this proof in the = {definition of id }
context of some language based on partial functions, such reverse (reverse xs)
as Haskell. To be concrete, let us assume that the natural = {reverse (reverse xs) = xs for total, finite xs}
number data type Nat is defined in the usual way,
xs.
data Nat = Zero | Succ Nat. (6)
Comparing to the previous proof we see that all steps
Note that this type contains many properly partial values are more or less identical, using similar lemmas, except for
that do not correspond to any natural number, and also a the second step, where two new lemmas are required. How
total but infinite value. Let us also assume that (+) and (−) did that step become so unwieldy? The problem is that,
are defined by although we know that (λx.x−y)◦(λx.y+x) = id given total
(+) = fold Succ, and (7) input, and also that xs only contains total natural numbers,
we have to manually propagate this precondition through
(−) = fold pred , (8)
reverse and map.
where fold :: (a → a) → a → Nat → a is the fold over One view of the problem is that the type system used
natural numbers (fold s z n replaces all occurrences of Succ is too weak. If there were a type for total, finite natural
in n with s, and Zero with z), and pred :: Nat → Nat is numbers, and similarly for lists, then the propagation would
the predecessor function with pred Zero = Zero. The other be handled by the types of reverse and map. The imaginary
functions and types are all standard [PJ03]; this implies total language used for the first proof effectively has such a
that the list type also contains properly partial and infinite type system.
values. On the other hand, note that the two versions of the
Given these definitions the property proved above is no program are written using identical syntax, and the semantic
longer true. The proof breaks down in various places. More rules for the total language and the partial language are
probably more or less identical when only total, finite (or Γ(x) = σ Γ[x 7→ σ] ` t : τ
even total, infinite) values are considered. Does not this
imply that we can get the second result above, with all Γ`x:σ Γ ` λx.t : σ → τ
preconditions, by using the first proof? The answer is yes, Γ ` t1 : σ → τ Γ ` t2 : σ
with a little extra effort, and proving this is what many of Γ ` t 1 t2 : τ
the sections below will be devoted to. In Section 9 we come Γ ` seq : σ → τ → τ Γ ` fix : (σ → σ) → σ
back to this example and spell out in full detail what “a Γ`?:1 Γ ` (,) : σ → τ → (σ × τ )
little extra effort” boils down to in this case. Γ ` fst : (σ × τ ) → σ Γ ` snd : (σ × τ ) → τ
Γ ` inl : σ → (σ + τ ) Γ ` inr : τ → (σ + τ )
3. Language
Γ ` case : (σ + τ ) → (σ → γ) → (τ → γ) → γ
This section defines the main language discussed in the text. Γ ` inµF : F µF → µF Γ ` outµF : µF → F µF
It is a strongly typed, monomorphic functional language
with recursive (polynomial) types and their corresponding Γ ` inνF : F νF → νF Γ ` outνF : νF → F νF
fold and unfold operators. Having only folds and unfolds is Γ ` foldF : (F σ → σ) → µF → σ
not a serious limitation; it is e.g. easy to implement primitive Γ ` unfoldF : (σ → F σ) → σ → νF
recursion over lists or natural numbers inside the language.
Since we want our results to be applicable to reasoning
about Haskell programs we include the explicit strictness Figure 1: Typing rules for L1 and L2 .
operator seq, which forces us to have lifted function spaces in
the domain-theoretic semantics given below. The semantics
of seq is defined in Figure 6. We discuss the most important ◦ 7→ λf g x.f (g x)
differences between Haskell and this language in Section 13.
Id 7→ λf x.f x
3.1 Static semantics Kσ 7→ λf x.x
The term syntax of the language, L1 , is inductively defined F × G 7→ λf x.seq x (F f (fst x), G f (snd x))
by
F + G 7→ λf x.case x (inl ◦ F f ) (inr ◦ G f )
t ::= x | t1 t2 | λx.t
| seq | ?
Figure 2: Syntactic sugar for terms.
| (,) | fst | snd (13)
| inl | inr | case
| inµF | outµF | inνF | outνF | foldF | unfoldF . Id σ 7→ σ
The pairing function (,) can be used in a distfix style, as in Kτ σ 7→ τ
(t1 , t2 ). The type syntax is defined by (F × G) σ 7→ F σ × G σ
σ, τ, γ ::= σ → τ | σ × τ | σ + τ | 1 | µF | νF (14) (F + G) σ 7→ F σ + G σ

and
Figure 3: Syntactic sugar for types.
F, G ::= Id | Kσ | F × G | F + G. (15)
The letters F and G range over functors; Id is the identity pointed ω-complete partial orders (CPOs). For CPOs ·⊥ is
functor and Kσ is the constant functor with Kσ τ = σ (in- the lifting operator, and h· → ·i is the continuous function
formally). The types µF and νF are inductive and coinduc- space constructor. Furthermore, for both sets and CPOs, ×
tive types, respectively. As an example, in the set-theoretic is cartesian product, and + is separated sum; A+B contains
semantics introduced below µ(K1 + Id ) represents finite nat- elements of the form inl (a) with a ∈ A and inr (b) with
ural numbers, and ν(K1 + Id ) represents natural numbers b ∈ B. The one-point set/CPO is denoted by 1, with ? as
extended with infinity. The type constructor → is sometimes the only element. The constructor for the (set- or domain-
used right associatively, without explicit parentheses. theoretic) semantic domain of the recursive type T , where
In order to discuss general recursion we define the lan- T is µF or νF , is denoted by in T , and the corresponding
guage L2 to be L1 extended with destructor is denoted by out T (often with omitted indices).
t ::= . . . | fix. (16) For more details about in and out, see below. Since we
use lifted function spaces, we use special notation for lifted
However, whenever fix is not explicitly mentioned, the lan- function application,
guage discussed is L1 (or the restriction L01 of L1 introduced (
below). ⊥, f = ⊥,
We only consider well-typed terms according to the typ- f @x = (17)
f x, otherwise.
ing rules in Figure 1. To ease the presentation we also intro-
duce some syntactic sugar for terms and types, see Figures 2 (This operator is left associative with the same precedence
and 3. as ordinary function application.) Many functions used on
the meta-level are not lifted, though, so @ is not used very
3.2 Dynamic semantics much below. Finally note that we are a little sloppy, in that
Before we define the semantics of the languages we need we do not write out liftings explicitly; we write (x, y) for a
to introduce some notation. We will use both sets and non-bottom element of (A × B)⊥ , for instance.
Now, two different denotational semantics are defined for
the languages introduced above, one domain-theoretic (J·K) Jσ → τ K = hJσK → Jτ Ki⊥ hhσ → τ ii = hhσii → hhτ ii
and one set-theoretic (hh·ii). (Note that when t is closed we Jσ × τ K = (JσK × Jτ K)⊥ hhσ × τ ii = hhσii × hhτ ii
sometimes use JtK as a shorthand for JtK ρ, and similarly
Jσ + τ K = (JσK + Jτ K)⊥ hhσ + τ ii = hhσii + hhτ ii
for hh·ii.) The domain-theoretic semantics is modelled on
languages like Haskell and can handle general recursion. The J1K = 1⊥ hh1ii = 1
set-theoretic semantics is modelled on total languages and
is only defined for terms in L1 . In Section 7 we will show 
how results obtained using the set-theoretic semantics can The codomain of the initial object in
JµF K = L(F )-Alg(CPO⊥ ).
be transformed into results on the domain-theoretic side.
The semantic domains for all types are defined in Fig-

The codomain of the initial object in
ure 4. We define the semantics of recursive types by appeal- hhµF ii =
F -Alg(SET).
ing to category-theoretic work [BdM96, FM91]. For instance, 
the set-theoretic semantic domain of µF is the codomain of The domain of the final object in
JνF K =
the initial object in F -Alg(SET). Here SET is the category L(F )-Coalg(CPO).
of sets and total functions, and F -Alg(SET) is the category hhνF ii = { The domain of the final object in F -Coalg(SET).
of F -algebras (in SET) and homomorphisms between them.
The initial object, which is known to exist given our limita-
tions on F , is a function in µF ∈ hhF µF → µF ii. The inverse Figure 4: Semantic domains for types.
of in µF exists and, as noted above, is denoted by out µF . Ini-
tiality of in µF implies that for any function f ∈ hhF σ → σii
there is a unique function fold F f ∈ hhµF → σii satisfying all those in this paper. For example, given the PER defined
the universal property in Section 5, we have that [inl ({c})] denotes the same
equivalence class no matter which element in c is chosen.
∀h ∈ hhµF → σii . h = fold F f ⇔ h ◦ in µF = f ◦ F h. (18)
This is how hhfoldF ii is defined. To define hhunfoldF ii we go
via the final object out νF in F -Coalg(SET) (the category of
5. Moral equality
F -coalgebras) instead. The semantics of all terms are given We will now inductively define a family of PERs ∼σ `on the´
in Figure 6. domain-theoretic semantic domains; with Rel (σ) = ℘ JσK2
The domain-theoretic semantics lives in the category we will have ∼σ ∈ Rel (σ). (Here ℘(X) is the power set of X.
CPO of CPOs and continuous functions. To define JµF K, The index σ will sometimes be omitted.)
the category CPO⊥ of CPOs and strict continuous functions If two values are related by ∼, then we say that they are
is also used. We want all types in the domain-theoretic morally equal. We use moral equality to formalise totality:
semantics to be lifted (like in Haskell). To model this we a value x ∈ JσK is said to be total iff x ∈ dom(∼σ ). The
lift all functors using L, which is defined in Figure 5. intention is that if σ does not contain function spaces, then
If we were to define JfoldF K using the same method as we should have x ∼σ y iff x and y are equal, total values.
for hhfoldF ii, then that would restrict its arguments to be For functions we will have f ∼ g iff f and g map (total)
strict functions. An explicit fixpoint is used instead. The related values to related values.
construction still satisfies the universal property associated The definition of totality given here should correspond to
with folds if all functions involved are strict [FM91]. For basic intuition. Sometimes another definition is used instead,
symmetry we also define JunfoldF K using an explicit fixpoint; where f ∈ Jσ → τ K is total iff f @x = ⊥ implies that x = ⊥.
that does not affect its universality property. That definition is not suitable for non-strict languages where
The semantics of fix is, as usual, given by a least fixpoint most semantic domains are not flat. As a simple example,
construction. consider JfstK; we will have JfstK ∈ dom(∼), so JfstK is total
We have been a little sloppy above, in that we have according to our definition, but JfstK@(⊥, ⊥) = ⊥.
not defined the action of the functor Kσ on objects. When Given the family of PERs ∼ we can relate the set-
working in SET we let Kσ A = hhσii, and in CPO and CPO⊥ theoretic semantic values with the total values of the
we let Kσ A = JσK. Otherwise the functors have their usual domain-theoretic semantics; see Sections 6 and 7.
meanings.
5.1 Non-recursive types
4. Partial equivalence relations The PER ∼σ→τ is a logical relation, i.e. we have the follow-
In what follows we will use partial equivalence relations, or ing definition for function spaces:
PERs for short. f ∼σ→τ g ⇔
A PER on a set S is a symmetric and transitive binary
relation on S. For a PER R on S, and some x ∈ S with xRx, f 6= ⊥ ∧ g 6= ⊥ ∧ (20)
define the equivalence class of x as ∀x, y ∈ JσK . x ∼σ y ⇒ f @x ∼τ g @y.
[x]R = { y y ∈ S, xRy } . (19) We need to ensure explicitly that f and g are non-bottom
because some of the PERs will turn out to have ⊥ ∈ dom(∼)
(The index R is omitted below.) Note that the equivalence
or dom(∼) = ∅.
classes partition dom(R) = { x ∈ S xRx }, the domain of
Pairs are related if corresponding components are related:
R. Let [R] denote the set of equivalence classes of R.
For convenience we will use the notation {c} for an x ∼σ×τ y ⇔ ∃x1 , y1 ∈ JσK , x2 , y2 ∈ Jτ K .
arbitrary element x ∈ c, where c is an equivalence class of x = (x1 , x2 ) ∧ y = (y1 , y2 ) ∧ (21)
some PER R ⊆ S 2 . This definition is of course ambiguous,
but the ambiguity disappears in many contexts, including x1 ∼σ y1 ∧ x2 ∼τ y2 .
Similarly, sums are related if they are of the same kind with
related components:
L(Id ) = Id
x ∼σ+τ y ⇔
L(Kσ ) = Kσ (∃x1 , y1 ∈ JσK .
L(F × G) = (L(F ) × L(G))⊥ x = inl (x1 ) ∧ y = inl (y1 ) ∧ x1 ∼σ y1 ) ∨ (22)
L(F + G) = (L(F ) + L(G))⊥ (∃x2 , y2 ∈ Jτ K .
x = inr (x2 ) ∧ y = inr (y2 ) ∧ x2 ∼τ y2 ) .
Figure 5: Lifting of functors.
The value ? of the unit type is related to itself and ⊥ is not
related to anything:
x ∼1 y ⇔ x = y = ?. (23)
JxK ρ = ρ(x) hhxii ρ = ρ(x) It is easy to check that what we have so far yields a family
Jt1 t2 K ρ = (Jt1 K ρ) @ (Jt2 K ρ) hht1 t2 ii ρ = (hht1 ii ρ) (hht2 ii ρ) of PERs.
Jλx.tK ρ = λv. JtK ρ[x 7→ v] hhλx.tii ρ = λv. hhtii ρ[x 7→ v]
 5.2 Recursive types
⊥, v1 = ⊥
JseqK = λv1 v2 . hhseqii = λv1 v2 .v2 The definition for recursive types is trickier. Consider lists.
v2 , otherwise
F∞ i When should one list be related to another? Given the in-
JfixK = λf. i=0 f @⊥ hhfixii is not defined. tentions above it seems reasonable for xs to be related to
J?K = ? hh?ii = ? ys whenever they have the same, total list structure (spine),
and elements at corresponding positions are recursively re-
J(,)K = λv1 v2 .(v1 , v2 ) hh(,)ii = λv1 v2 .(v1 , v2 ) lated. In other words, something like

⊥, v = ⊥
JfstK = λv. hhfstii = λ(v1 , v2 ).v1 xs ∼µ(K1 +(Kσ ×Id)) ys ⇔
v1 , v = (v1 , v2 )
“(xs = in (inl (?)) ∧ ys = in (inl (?)))

⊥, v = ⊥
JsndK = λv. hhsndii = λ(v1 , v2 ).v2 ∨ ∃x, y ∈ JσK , xs 0 , ys 0 ∈ Jµ(K1 + (Kσ × Id ))K . (24)
v2 , v = (v1 , v2 )
JinlK = λv.inl (v) hhinlii = λv.inl (v) xs = in (inr ((x, xs 0 ))) ∧ ys = in (inr
” ((y, ys 0
)))
JinrK = λv.inr (v) hhinrii = λv.inr (v) ∧ x ∼σ y ∧ xs 0 ∼µ(K1 +(Kσ ×Id)) ys 0 .
8
<⊥, v =⊥ We formalise the intuition embodied in (24) by defining
JcaseK = λv f1 f2 . f1 @v1 , v = inl (v1 ) a relation transformer RT (F ) for each functor F ,
:f @v , v = inr (v )
2 2 2
 RT (F ) ∈ Rel (µF ) → Rel (µF )
f v , v = inl (v1 )
hhcaseii = λv f1 f2 . 1 1 RT (F
˘ )(X) = (25)
f2 v2 , v = inr (v2 )
(in x, in y) (x, y) ∈ RT 0µF (F )(X) .
¯

JinµF K = The initial object in L(F )-Alg(CPO⊥ ),
viewed as a morphism in CPO. The helper RT 0σ (F ) is defined by

hhinµF ii = The initial object in F -Alg(SET), viewed as RT 0σ (F ) ∈ Rel (σ) → Rel (F σ)
a morphism in SET.
 RT 0σ (Id )(X) =X
JoutνF K = The final object in L(F )-Coalg(CPO), RT 0σ (Kτ )(X) = ∼τ
viewed as a morphism in CPO.
 RT0σ (F1 × F2 )(X) =
(x1 , y1 ) ∈ RT 0σ (F1 )(X),
ff
The final object in F -Coalg(SET), viewed (26)
hhoutνF ii = ((x1 , x2 ), (y1 , y2 )) 0
as a morphism in SET. (x2 , y2 ) ∈ RT σ (F2 )(X)
JfoldF K = λf. JfixK@(λg.f ◦ JF K@g ◦ JoutµF K) RT 0σ (F1 + F2 )(X) =
( { (inl (x1 ) , inl (y1 )) (x1 , y1 ) ∈ RT 0σ (F1 )(X) } ∪
The unique morphism in F -Alg(SET)
hhfoldF ii = λf. from hhinµF ii to f , viewed as a morphism { (inr (x2 ) , inr (y2 )) (x2 , y2 ) ∈ RT 0σ (F2 )(X) } .
in SET.
The relation transformer RT (F ) is defined for inductive
JunfoldF K = λf. JfixK@(λg. JinνF K ◦ JF K@g ◦ f ) types. However, replacing µF with νF in the definition is
enough to yield a transformer suitable for coinductive types.
(
The unique morphism in F -Coalg(SET)
hhunfoldF ii = λf. from f to hhoutνF ii, viewed as a Now, note that RT (F ) is a monotone operator on the
morphism in SET. complete lattice (Rel (µF ) , ⊆). This implies that it has both
least and greatest fixpoints [Pri02], which leads to the fol-
Figure 6: Semantics of well-typed terms, for some context lowing definitions:
ρ mapping variables to semantic values. The se- x ∼µF y ⇔ (x, y) ∈ µRT (F ) and (27)
mantics of inνF and outµF are the inverses of the
semantics of outνF and inµF , respectively. x ∼νF y ⇔ (x, y) ∈ νRT (F ) . (28)
These definitions may not be entirely transparent. If we
go back to the list example and expand the definition of
RT (K1 + (Kσ × Id )) we get consisting of all terms from L1 which contain no uses of seq
at type χ → σ → σ.
RT (K1 + (Kσ × Id ))(X) =
Now, by using induction over the term structure instead
{ (in (inl (?)), in (inl (?))) } ∪ of the type structure, and then following the rest of IIICI, it
(29)

(in (inr ((x, xs))), x, y ∈ JσK , x ∼ y,
ff is shown that the fundamental theorem of logical relations
in (inr ((y, ys)))) (xs, ys) ∈ X
. holds for any term t in L01 : if ρ(x) ∼ ρ0 (x) for all free
variables x in a term t, then
The least and greatest fixpoints of this operator correspond
to our original aims for ∼µ(K1 +(Kσ ×Id)) and ∼ν(K1 +(Kσ ×Id)) . JtK ρ ∼ JtK ρ0 . (35)
(Note that we never consider an infinite inductive list as The fundamental theorem is important because it implies
being total.) that JtK ∈ dom(∼σ ) for all closed terms t : σ in L01 . In
It is still possible to show that what we have defined other words, all closed terms in L01 denote total values.
actually constitutes a family of PERs, but it takes a little Note, however, that JfixK ∈
/ dom(∼) (at most types) since
more work. First note the two proof principles given by the Jλx.xK ∈ dom(∼) and Jfix (λx.x)K = ⊥.
definitions above: induction,
∀X ⊆ JµF K2 . RT (F )(X) ⊆ X ⇒ µRT (F ) ⊆ X, (30) 5.4 Examples
With moral equality defined we can prove a number of laws
and coinduction, for ∼ which are not true for =. As an example, consider
η-equality (combined with extensionality):
∀X ⊆ JνF K2 . X ⊆ RT (F )(X) ⇒ X ⊆ νRT (F ) . (31)
∀f, g ∈ Jσ → τ K .
Many proofs needed for this paper proceed according to (36)
a scheme similar to the following one, named IIICI below (∀x ∈ JσK . f @x = g @x) ⇔ f = g.
(Induction-Induction-Induction-Coinduction-Induction): This law is not valid, since the left hand side is satisfied by
• First induction over the type structure. the distinct values f = ⊥ and g = λv.⊥. On the other hand,
• For inductive types, induction according to (30) and then the following variant follows immediately from the definition
of ∼:
induction over the functor structure.
• For coinductive types, coinduction according to (31) and ∀f, g ∈ dom(∼σ→τ ) .
(37)
then induction over the functor structure. (∀x ∈ dom(∼σ ) . f @x ∼ g @x) ⇔ f ∼ g.
Using this scheme it is proved that ∼ is a family of PERs As another example, consider currying (1). The cor-
[Dan05]. responding statement, Jcurry ◦ uncurryK ∼ Jid K, is easily
proved using the fundamental theorem (35) and the η-
5.3 Properties law (37) above. We can also prove surjective pairing. Since
We can prove that ∼ satisfies a number of other properties p ∈ dom(∼σ×τ ) implies that p = (x, y) for some x ∈
as well. Before leaving the subject of recursive types, we note dom(∼σ ) and y ∈ dom(∼τ ) we get J(fst t, snd t)K ρ = JtK ρ,
that given that JtK ρ ∈ dom(∼).
x ∼F µF y ⇔ in x ∼µF in y (32)
6. Partial surjective homomorphism
and
For the main theorem (Section 7) we need to relate values
x ∼νF y ⇔ out x ∼F νF out y (33) in hhσii to values in [∼σ ], the set of equivalence classes of ∼σ .
Due to cardinality issues there is in general no total bijection
hold, as well as the symmetric statements where µF is between these sets; consider σ = (Nat → Nat) → Nat with
replaced by νF and vice versa. This is proved using a method Nat = µ(K1 + Id ), for instance. We can define a partial
similar to IIICI, but not quite identical. Another method surjective homomorphism [Fri75] from hhσii to [∼σ ], though.
similar to IIICI is used to verify that ∼ satisfies one of This means that for each type σ there is a partial, surjective
our initial goals: if σ does not contain function spaces, then function jσ ∈ hhσii → ˜ [∼σ ], which for function types satisfies
x ∼σ y iff x, y ∈ dom(∼σ ) and x = y.
Continuing with order related properties, it is proved (jτ1 →τ2 f ) (jτ1 x) = jτ2 (f x) (38)
using induction over the type structure that ∼σ is monotone whenever f ∈ dom(jτ1 →τ2 ) and x ∈ dom(jτ1 ). (Here → ˜ is
when seen as a function ∼σ ∈ JσK2 → 1⊥ . This implies that the partial function space constructor and dom(f ) denotes
all equivalence classes are upwards closed. We also have (by the domain of the partial function f . Furthermore we define
induction over the type structure) that ⊥ ∈ / dom(∼σ ) for [f ] [x] = [f @x], which is well-defined.)
almost all types σ. The only exceptions are given by the The functions jσ ∈ hhσii →
˜ [∼σ ] are simultaneously proved
grammar to be well-defined and surjective by induction over the
χ ::= νId | µKχ | νKχ . (34) type structure plus some other techniques for the (omitted)
recursive cases. The following basic cases are easy:
Note that JχK = { ⊥ } for all these types.
The (near-complete) absence of bottoms in dom(∼) gives jσ×τ ∈ hhσ × τ ii →
˜ [∼σ×τ ]
(39)
us an easy way to show that related values are not al- jσ×τ (x, y) = [({jσ x} , {jτ y})] ,
ways equal: at most types JseqK ∼ Jλx.λy.yK but JseqK 6=
jσ+τ ∈ hhσ + τ ii →
˜ [∼σ+τ ]
Jλx.λy.yK. This example breaks down when seq is used at
type χ → σ → σ (unless dom(∼σ ) = ∅). To be able to prove jσ+τ inl (x) = [inl ({jσ x})] (40)
the fundamental theorem below, let L01 denote the language jσ+τ inr (y) = [inr ({jτ y})] ,
and (CoNat, isInfinite etc. are defined in Section 6.) We get
j isIsInfinite = j (λf.False) (both defined), so j is not
j1 ∈ hh1ii →
˜ [∼1 ] injective. In fact, no j which satisfies the main theorem (45)
(41)
j1 ? = [?] . and uses the definition above for function spaces (43) can
Note the use of {·} to ease the description of these functions. be injective.
It turns out to be impossible in general to come up
with a total definition of j for function spaces. Consider
the function isInfinite ∈ hhCoNat → Bool ii (with CoNat = 8. Category-theoretic approach
ν(K1 + Id ) and Bool = 1 + 1) given by
( Equation (46) above is useful partly because SET is a well-
True, j n = [ω] , understood category. For those who prefer to work ab-
isInfinite n = (42)
False, otherwise. stractly instead of working in SET, the following result may
be a useful substitute. We define the category PER∼ as fol-
(Here ω = JunfoldK1 +Id inr ?K is the infinite “natural num- lows:
ber”, True = inl (?) and False = inr (?).) Any surjective
homomorphism j must be undefined for isInfinite. Objects The objects are types σ (without any restrictions).
Instead we settle for a partial definition. We employ a Morphisms The morphisms of type σ → τ are the elements
technique, originating from Friedman [Fri75], which makes it of [∼σ→τ ], i.e. equivalence classes of total functions.
easy to prove that j is homomorphic: if possible, let jτ1 →τ2 f
Composition [f ] ◦ [g] = [λv.f @(g @v)].
be the element g ∈ [∼τ1 →τ2 ] satisfying
∀x ∈ dom(jτ1 ) . g (jτ1 x) = jτ2 (f x). (43) This category is bicartesian closed, with initial algebras and
final coalgebras for (at least) polynomial functors. All the
If a g exists, then it can be shown to be unique (using
laws that follow from this statement can be used to reason
surjectivity of jτ1 ). If no such g exists, then let jτ1 →τ2 f
about programs. For instance, it should not be hard to
be undefined. To show that jτ1 →τ2 is surjective we use a
repeat the total proofs from this paper using such laws.
lemma stating that hhσii is empty iff [∼σ ] is.
For this method to be immediately useful, the various
The definition of j for inductive and coinductive types
constructions involved should correspond closely to those in
follows the idea outlined for the basic cases above, but is
the underlying language. And they do:
more involved, and we omit it here due to space constraints.
Initial object The initial object is µId , with the unique
7. Main theorem morphism of type µId → σ given by [λv.⊥].
Now we get to our main theorem. Assume that t is a term Final object The final object is 1, with the unique mor-
in L01 with contexts ρ and ρ0 satisfying phism of type σ → 1 given by [λv.?]. Note that νId is
isomorphic to 1.
ρ(x) ∈ dom(∼) ∧ j ρ0 (x) = [ρ(x)] (44)
Products The product of σ and τ is σ × τ . The projections
for all variables x free in t. Then we have that j (hhtii ρ0 ) is are [JfstK] and [JsndK], and given [f ] : γ → σ and
well-defined and [g] : γ → τ the unique morphism which “makes the
j hhtii ρ0 = [JtK ρ] .
` ´
(45) diagram commute” is [λv.(f @v, g @v)].
Coproducts The coproduct of σ and τ is σ + τ . The
This result can be proved by induction over the structure injections are [JinlK] and [JinrK], and given [f ] : σ → γ
of t, induction over the size of values of inductive type and and [g] : τ → γ the unique morphism which “makes the
coinduction for coinductive types. The case where t is an diagram commute” is [λv. JcaseK@v @f @g].
application relies heavily on j being homomorphic. Note
that the proof depends on the particular definition of j given Exponentials The exponential of τ and σ is σ → τ . The
in Section 6; if we wanted to use a different partial surjective apply morphism is [λ(f, x).f @x], and currying is given
homomorphism then the proof would need to be modified. by the morphism [λf x y.f @(x, y)].
As a corollary to the main theorem we get, for any two Initial algebras For a polynomial functor F the corre-
terms t1 , t2 : σ in L01 with two pairs of contexts ρ1 , ρ01 and sponding initial F -algebra is (µF, [JinµF K]). Given the
ρ2 , ρ02 both satisfying the conditions of (44) (for t1 and t2 , F -algebra [f ] : F σ → σ, the unique homomorphism
respectively), that from [JinµF K] is [JfoldF K@f ].
Final coalgebras For a polynomial functor F the corre-
hht1 ii ρ01 = hht2 ii ρ02 ⇒ Jt1 K ρ1 ∼ Jt2 K ρ2 . (46)
sponding final F -coalgebra is (νF, [JoutνF K]). Given the
In other words, if we can prove that two terms are equal in F -coalgebra [f ] : σ → F σ, the unique homomorphism
the world of sets, then they are morally equal in the world of to [JoutνF K] is [JunfoldF K@f ].
domains. When formalised like this the reasoning performed
using set-theoretic methods, “fast and loose” reasoning, is The proofs of these properties are rather easy, and do not
no longer loose. require constructions like j.
If j had been injective, then (46) would have been an The partial surjective homomorphism j fits into the
equivalence. That would mean that we could handle un- category-theoretic picture anyway: it can be extended to
equalities (6=). The particular j defined here is not injec- a partial functor to PER∼ from the category which has
tive, which can be shown using the function isIsInfinite ∈ types σ as objects, total functions between the correspond-
hh(CoNat → Bool ) → Bool ii given by ing set-theoretic domains hhσii as morphisms, and ordinary
( function composition as composition of morphisms. The ob-
True, f = isInfinite, ject part of this functor is the identity, and the morphism
isIsInfinite f = (47)
False, otherwise. part is given by the function space case of j.
9. Review of example a list of numbers and calculates their running sum, and diffs
After having introduced the main theoretic body, let us now performs the left inverse operation, along the lines of
revisit the example from Section 2. sums [3, 1, 4, 1, 5] = [3, 4, 8, 9, 14], and (51)
We verified that revMap = reverse ◦ map (λx.x − y) is
diffs [3, 4, 8, 9, 14] = [3, 1, 4, 1, 5] (52)
the left inverse of mapRev = map (λx.y + x) ◦ reverse in a
total setting. Let us express this result using the language (using standard syntactic sugar for lists and natural num-
introduced in Section 3. The type of the functions becomes bers). The aim is to prove that
ListNat → ListNat, where ListNat is the inductive type
µ(K1 + (KNat × Id )) of lists of natural numbers, and Nat is hhdiffs ◦ sumsii = hhid ii . (53)
the inductive type µ(K1 + Id ). Note also that the functions We do that in Section 10.1. Alternatively, we can implement
reverse, map, (+) and (−) can be expressed using folds, so the functions in L2 and prove that
the terms belong to L1 . Finally note that seq is not used at
a type χ → σ → σ with ⊥ ∈ dom(∼χ ), so the terms belong Jdiffs ◦ sumsK@xs = xs (54)
to L01 , and we can make full use of the theory. for all total, finite lists xs ∈ JListNatK containing total,
Our earlier proof in effect showed that finite natural numbers. That is done in Section 10.2. We
hhrevMap ◦ mapRev ii [y 7→ n] = hhid ii (48) then compare the experiences in Section 10.3.

for an arbitrary n ∈ hhNatii, which by (46) implies that 10.1 Using total reasoning
JrevMap ◦ mapRev K y 7→ n0 ∼ListNat→ListNat Jid K (49) First let us implement the functions in L01 . To make the
ˆ ˜
development easier to follow, we use some syntax borrowed
whenever n0 ∈ dom(∼Nat ) and [n0 ] = j n for some n ∈ from Haskell. We also use the function foldr , modelled on
hhNatii. By the fundamental theorem (35) and the main its Haskell namesake:
theorem (45) we have that JtK satisfies the conditions for
n0 for any closed term t ∈ L01 of type Nat. This includes all foldr : (σ → (τ → τ )) → τ
total, finite natural numbers. → µ(K1 + (Kσ × Id )) → τ
It remains to interpret ∼ListNat→ListNat . Denote the left foldr f x = (55)
hand side of (49) by f . The equation implies that f @xs ∼ foldK1 +(Kσ ×Id) (λy.case y (λ .x)
ys whenever xs ∼ ys. By using the fact (mentioned in (λp.f (fst p) (snd p))).
Section 5.3) that xs ∼ListNat ys iff xs ∈ dom(∼ListNat ) and
xs = ys, we can restate the equation as f @xs = xs whenever The following is a simple, albeit inefficient, recursive
xs ∈ dom(∼ListNat ). implementation of sums:
We want xs ∈ dom(∼ListNat ) to mean the same as “xs sums : ListNat → ListNat
is total and finite”. We defined totality to mean “related (56)
sums = foldr add [ ],
according to ∼” in Section 5, so xs ∈ dom(∼ListNat ) iff xs
is total. We have not defined finiteness, though. However, where
with any reasonable definition we can be certain that x ∈
dom(∼σ ) is finite if σ does not contain function spaces or add : Nat → ListNat → ListNat
(57)
coinductive types; in the absence of such types we can define add x ys = x : map (λy.x + y) ys.
a function size σ ∈ dom(∼σ ) → N which has the property
that size x0 < size x whenever x0 is a structurally smaller Here (+) and (−) (used below) are implemented as folds, in
part of x, such as with x = inl (x0 ) or x = in (x0 , x00 ). a manner analogous to (7) and (8) in Section 2. The function
Hence we have arrived at the statement proved by the map can be implemented using foldr :
more elaborate proof in Section 2: for all total and finite map : (σ → τ ) → µ(K1 + (Kσ × Id ))
lists xs and all total and finite natural numbers n, → µ(K1 + (Kτ × Id )) (58)
J(revMap ◦ mapRev ) xsK [y 7→ n] = JxsK . (50) map f = foldr (λx ys.f x : ys) [ ].
This means that we have proved a result about the partial The definition of diffs uses similar techniques:
language without having to manually propagate precondi-
diffs : ListNat → ListNat
tions. At first glance it may seem as if the auxiliary argu- (59)
ments spelled out in this section make using total methods diffs = foldr sub [ ],
more expensive than we first indicated. However, note that
where
the various parts of these arguments only need to be car-
ried out at most once for each type. They do not need to be sub : Nat → ListNat → ListNat
repeated for every new proof. (60)
sub x ys = x : toHead (λy.y − x) ys.
The helper function toHead applies a function to the first el-
10. Partial reasoning is sometimes ement of a non-empty list, and leaves empty lists unchanged:
preferable
toHead : (Nat → Nat) → ListNat → ListNat
This section discusses an example of a different kind from
toHead f (y : ys) = f y : ys (61)
the one given in Section 2; an example where partial rea-
soning (i.e. reasoning using the domain-theoretic semantics toHead f [ ] = [ ].
directly) seems to be more efficient than total reasoning. Now let us prove (53). We can use fold fusion [BdM96],
We define two functions sums and diffs, both of type
ListNat → ListNat, with the inductive types ListNat and g ◦ foldr f e = foldr f 0 e0
(62)
Nat defined just like in Section 9. The function sums takes ⇐ g e = e0 ∧ ∀x, y. g (f x y) = f 0 x (g y).
(For simplicity we do not write out the semantic brackets In total languages inductive and coinductive types cannot
hh·ii, or any contexts.) We have easily be mixed; we do not have the same problem in partial
diffs ◦ sums = id languages.
The corecursive definition of sums,
⇔ {definition of sums, id = foldr (:) [ ]}
diffs ◦ foldr add [ ] = foldr (:) [ ] sums : ListNat → ListNat
(70)
sums xs = unfoldr next (0, xs),
⇐ {fold fusion}
diffs [ ] = [ ] ∧ with helper next,
∀x, ys. diffs (add x ys) = x : diffs ys.
next : (Nat × ListNat)
The first conjunct is trivial, and the second one can be → (1 + (Nat × (Nat × ListNat)))
proved by using the lemmas (71)
next (e, [ ]) = inl ?
(λy.y − x) ◦ (λy.x + y) = id (63) next (e, x : xs) = inr (e + x, (e + x, xs)),
and should be just as easy to follow as the recursive one, if not
easier. Here we have used the same definitions of (+) and (−)
diffs ◦ map (λy.x + y) = toHead (λy.x + y) ◦ diffs. (64) as above, and 0 is shorthand for inNat (inl ?). The definition
To prove the second lemma we use fold-map fusion [BdM96], of diffs,
foldr f e ◦ map g = foldr (f ◦ g) e. (65) diffs : ListNat → ListNat
(72)
We have diffs xs = unfoldr step (0, xs),
diffs ◦ map (λy.x + y) with step,
= {definition of diffs}
foldr sub [ ] ◦ map (λy.x + y) step : (Nat × ListNat)
→ (1 + (Nat × (Nat × ListNat)))
= {fold-map fusion} (73)
step (e, [ ]) = inl ?
foldr (sub ◦ (λy.x + y)) [ ] step (e, x : xs) = inr (x − e, (x, xs)),
= {fold fusion, see below}
is arguably more natural than the previous one.
toHead (λy.x + y) ◦ foldr sub [ ] Now we can prove (54) for all total lists containing total,
= {definition of diffs} finite natural numbers; we do not need to restrict ourselves
toHead (λy.x + y) ◦ diffs. to finite lists. To do that we use the approximation lemma
[HG01],
To finish up we have to verify that the preconditions for fold
fusion are satisfied above, xs = ys ⇔ ∀n ∈ N. approx n xs = approx n ys, (74)
toHead (λy.x + y) [ ] = [ ], (66) where the function approx is defined by
and approx ∈ N → Jµ(K1 + (Kσ × Id ))K
∀y, ys. toHead (λy.x + y) (sub y ys) = → Jµ(K1 + (Kσ × Id ))K
(67) approx 0 =⊥
(sub ◦ (λy.x + y)) y (toHead (λy.x + y) ys). (75)
approx (n + 1) ⊥ =⊥
The first one is yet again trivial, and the second one can be approx (n + 1) [ ] = []
proved by using the lemma
approx (n + 1) (x : xs) = x : approx n xs.
λz.z − y = (λz.z − (x + y)) ◦ (λy.x + y). (68)
Note that this definition takes place on the meta-level, since
10.2 Using partial reasoning the natural numbers N do not correspond to any type in our
Let us now see what we can accomplish when we are not language.
restricted to a total language. Yet again we borrow some We have the following (yet again ignoring semantic brack-
syntax from Haskell; most notably we do not use fix directly, ets and contexts and also all uses of @):
but define functions using recursive equations instead. ∀ total xs containing total, finite numbers.
The definitions above used structural recursion. The pro-
grams below instead use structural corecursion, as captured (diffs ◦ sums) xs = xs
by the function unfoldr , which is based on the standard un- ⇔ {approximation lemma}
fold for lists as given by the Haskell Report [PJ03]: ∀ total xs containing total, finite numbers.
unfoldr : (τ → (1 + (σ × τ ))) → τ ∀n ∈ N. approx n ((diffs ◦ sums) xs) = approx n xs
→ µ(K1 + (Kσ × Id )) ⇔ {predicate logic, definition of diffs, sums and ◦}
unfoldr f b = case (f b) (69)
∀n ∈ N. ∀ total xs containing total, finite numbers.
(λ .[ ])
(λp.fst p : unfoldr f (snd p)). approx n (unfoldr step (0, unfoldr next (0, xs))) =
Note that we cannot use unfold here, since it has the wrong approx n xs
type. We can write unfoldr with the aid of fix, though. ⇐ {generalise, 0 is total and finite}
∀n ∈ N. ∀ total xs containing total, finite numbers. 11. Strict languages
∀ total and finite y. We can treat strict languages (at least the somewhat odd
approx n (unfoldr step (y, unfoldr next (y, xs))) = language introduced below) using the framework developed
so far by modelling strictness using seq, just like strict
approx n xs. data type fields are handled in the Haskell Report [PJ03].
We proceed by induction on the natural number n. The For simplicity we reuse the previously given set-theoretic
n = 0 case is trivial. For n = k + 1 we have two cases, semantics, and also all of the domain-theoretic semantics,
xs = [ ] and xs = z : zs (with z being a total, finite natural except for one rule, the one for application.
number, etc.). The first case is easy, whereas the second one More explicitly, we define the domain-theoretic, strict
requires a little more work: semantics J·K⊥ by JσK⊥ = JσK for all types. For terms we
let application be strict,
approx (k + 1) (` ´ ` ´
(unfoldr step (y, unfoldr next (y, z : zs))) Jt1 K⊥ ρ @ Jt2 K⊥ ρ , Jt2 K⊥ ρ 6= ⊥,
Jt1 t2 K⊥ ρ = (76)
= {definition of unfoldr , next and step} ⊥, otherwise.
approx (k + 1) Abstractions are treated just as before,
((y + z) − y :
Jλx.tK⊥ ρ = λv. JtK⊥ ρ[x 7→ v] , (77)
unfoldr step (y + z, unfoldr next (y + z, zs)))
and whenever t is not an application or abstraction we let
= {(y + z) − y = z for y, z total and finite}
JtK⊥ ρ = JtK ρ.
approx (k + 1) We then define a type-preserving syntactic translation ∗
(z : unfoldr step (y + z, unfoldr next (y + z, zs))) on L1 , with the intention of proving that JtK⊥ ρ = Jt∗ K ρ.
The translation is as follows:
= {definition of approx } 8
∗ ∗ ∗
z : approx k <seq t2 (t1 t2 ), t = t1 t2 ,
>
∗ ∗
t = λx.t1 , t = λx.t1 , (78)
(unfoldr step (y + z, unfoldr next (y + z, zs))) >
:t, otherwise.
= {inductive hypothesis, y + z is total and finite}
The desired property follows easily by induction over the
z : approx k zs
structure of terms. It is also easy to prove that hhtii ρ =
= {definition of approx } hht∗ ii ρ.
approx (k + 1) (z : zs). Given these properties we can easily prove the variants
of the main theorem (45) and its corollary (46) that result
Note that we need a lemma stating that y + z is total and from replacing J·K with J·K⊥ . The category-theoretic results
finite whenever y and z are. from Section 8 immediately transfer to this new setting since
10.3 Comparison the category is the same and JtK⊥ = JtK for all closed terms
t not containing applications.
The last proof above, based on reasoning using domain-
theoretic methods, is arguably more concise than the pre-
vious one, especially considering that it is more detailed. It 12. Related work
also proves a stronger result since it is not limited to finite The notion of totality used above is very similar to that
lists. used by Scott [Sco76]. Aczel’s interpretation of Martin-Löf
When we compare to the example in Section 2 we see type theory [Acz77] is also based on similar ideas, but
that we were fortunate not to have to explicitly propagate types are modelled as predicates instead of PERs. That
any preconditions through functions in the domain-theoretic work has been extended by Smith [Smi84], who interprets
proof here, except in the penultimate step in the last case a polymorphic variant of Martin-Löf type theory in an
above. Notice especially the second step in the last case. untyped language which shares many properties with our
The variables y and z were assumed to be finite and total, partial language L2 ; he does not consider coinductive types
and hence the lemma (y + z) − y = z could immediately be or seq, though. Beeson considers a variant of Martin-Löf
applied. type theory with W -types [Bee82]. W -types can be used
There is of course the possibility that the set-theoretic to model strictly positive inductive and coinductive types
implementation and proof are unnecessarily complex. Note [Dyb97, AAG05]. Modelling coinductive types can also be
for instance that the domain-theoretic variants work equally done in other ways [Hal87], and the standard trick of coding
well in the set-theoretic world, if we go for coinductive non-strict evaluation using function spaces (force and delay)
instead of inductive lists, and replace the approximation may also be applicable. Furthermore it seems as if Per
lemma with the take lemma [HG01]. Using such techniques Martin-Löf, in unpublished work, considered lifted function
in a sense leads to more robust results, since they never spaces in a setting similar to [Smi84].
require preconditions of the kind above to be propagated The method we use to relate the various semantic models
manually. is basically that of Friedman [Fri75]; his method is more
However, since inductive and coinductive types are not abstract, but defined for a language with only base types,
easily mixed we cannot always go this way. If we for example natural numbers and functions.
want to process the result of sums using a fold, we cannot use Scott mentions that a category similar to PER∼ is bi-
coinductive lists. In general we cannot use hylomorphisms cartesian closed [Sco76].
[MFP91], unfolds followed by folds, in a total setting. If we There is a vast body of literature written on the subject
want or need to use a hylomorphism, then we have to use a of Aczel interpretations, PER models of types, and so on,
partial language. and some results may be known as folklore without having
been published. This text can be seen as a summary of note that, by adding and verifying some extra axioms, the
some results, most of them previously known in one form category-theoretic approach can be used to reason about
or another, that we consider important for reasoning about unequalities (6=). Given this ability it should be possible
functional programs. By writing down the results we make to handle more complex logical formulas as well; we have
the details clear. Furthermore we apply the ideas to the not examined this possibility in detail, though. Since the
problem of reasoning about programs, instead of using them method of Section 7 (without injective j) cannot handle
only to interpret one theory in another. This is quite a unequalities, it is in some sense weaker.
natural idea, so it is not unreasonable to expect that others It should be clear from the examples above that using
have made similar attempts. We know about [Dyb85], in total methods can sometimes be cheaper than partial ones,
which Dybjer explains how one can reason about an untyped and sometimes more expensive. We have not performed any
partial language using total methods for expressions that are quantitative measurements, so we cannot judge the relative
typeable (corresponding to our total values). We have not frequency of these two outcomes. One reasonable conclusion
found any work that discusses fast and loose reasoning for is that it would be good if total and partial methods could be
strict languages. mixed without large overheads. We have not experimented
Another angle on the work presented here is that we want with that, but can still make some remarks.
to get around the fact that many category-theoretic isomor- First it should be noted that ∼ is not a congruence:
phisms are missing in categories like CPO. For instance, one we can have x ∼ y but still have f @x 6∼ f @y (if f ∈ /
cannot have a cartesian closed category with coproducts and dom(∼)). We can still use an established fact like x ∼ y
fixpoints for all morphisms [HP90]. In this work we disallow by translating the statement into a form using preconditions
all fixpoints except well-behaved ones that can be expressed and equality, like we did in Section 9. This translation is easy,
as folds and unfolds. Another approach is to disallow recur- but may result in many nontrivial preconditions, perhaps
sion explicitly for sum types [BB91]. The MetaSoft project more preconditions than partial reasoning would lead to.
(see e.g. [BT83, Bli87]) advocated using “naive denotational When this is not the case it seems as if using total reasoning
semantics”, a denotational semantics framework that does in some leaves of a proof, and then partial reasoning on the
not incorporate reflexive domains. This means that some fix- top-level, should work out nicely.
points (both on the type and the value level) are disallowed, Another observation is that, even if some term t is written
with the aim that the less complex denotational structures in a partial style (using fix), we may still have JtK ∈ dom(∼).
may instead simplify understanding. This would for example be the case if we implemented foldr
A case can be made for sometimes reasoning using a con- (see Section 10.1) using fix instead of fold. Hence, if we
servative approximate semantics, obtaining answers that are explicitly prove that JtK ∈ dom(∼) then we can use t in a
not always exactly correct [DJ04, discussion]. Programmers total setting. This proof may be expensive, but enables us to
using languages like Haskell often ignore issues related to use total reasoning on the top-level, with partial reasoning
partiality anyway, so the spirit of many programs can be in some of the leaves.
captured without treating all corner cases correctly. The Now on to other issues. An obvious question is whether
methods described in this paper in a sense amount to us- one can extend the results to more advanced languages
ing an approximate semantics, but with the ability to get incorporating stronger forms of recursive types, polymor-
exactly correct results by translating results involving ∼ to phism, or type constructors. Adding polymorphism would
equalities with preconditions. give us an easy way to transform free theorems [Rey83,
There is some correspondence between our approach and Wad89] from the set-theoretic side (well, perhaps not set-
that of total and partial correctness reasoning for imperative theoretic [Rey84]) to the domain-theoretic one. It should be
programs, for example with Dijkstra’s wp and wlp predi- interesting to compare those results to other work involving
cate transformers [Dij76]. In both cases, simpler approxi- free theorems and seq [JV04].
mate methods can be used to prove slightly weaker results However, the main motivation for treating a more ad-
than “what one really wants”. However, in the w(l)p case, vanced type system is that we want the results to be ap-
conjoining partial correctness with termination yields total plicable to languages like Haskell, and matching more fea-
correctness. In contrast, in our case, there is in general no tures of Haskell’s type system is important for that goal.
(known) simple adjustment of a fast and loose proof to make Still, the current results should be sufficient to reason about
a true proof of the same property. Nevertheless, the fast and monomorphic Haskell programs using only polynomial re-
loose proof already yields a true proof of a related property. cursive types, with one important caveat: Haskell uses the
Sometimes it is argued that total functional programming sums-of-products style of data type definitions. When sim-
should be used to avoid the problems with partial languages. ulating such definitions using binary type constructors, ex-
Turner does that in the context of a language similar to tra bottoms are introduced. As an example, Jµ(K1 + Id )K
the total one described here [Tur96], and discusses methods contains the different values in (inl (⊥)) and in (inl (?)),
for circumventing the limitations associated with mandatory but since the constructor Zero is nullary the Haskell data
totality. type Nat from Section 2 does not contain an analogue of
in (inl (⊥)). One simple but unsatisfactory solution to this
13. Discussion and future work problem is to restrict the types used on the Haskell side to
analogues of those discussed in this paper. Another approach
We have justified reasoning about functional languages con- is of course to rework the theory using sums-of-products
taining partial and infinite values and lifted types, including style data types. We foresee no major problems with this,
lifted functions, using total methods. Two total methods but some details may require special attention.
were described, one based on a set-theoretic semantics and
one based on a bicartesian closed category, both using a par-
tial equivalence relation to interpret results in the context Acknowledgments
of a domain-theoretic semantics. Thanks to Thierry Coquand and Peter Dybjer for pointing
We have focused on equational reasoning. However, out related work and giving us feedback. Thanks also to
Koen Claessen, Jörgen Gustavsson, Ulf Norell, Ross Pater- Letters, 79(4):197–201, 2001.
son, K. V. S. Prasad, David Sands and Josef Svenningsson [HP90] Hagen Huwig and Axel Poigné. A note on
for participating in discussions and/or giving feedback. inconsistencies caused by fixpoints in a cartesian
closed category. Theoretical Computer Science,
73(1):101–112, 1990.
References
[Jeu90] J. Jeuring. Algorithms from theorems. In
[AAG05] Michael Abbott, Thorsten Altenkirch, and Neil Programming Concepts and Methods, pages 247–
Ghani. Containers: Constructing strictly positive 266. North-Holland, 1990.
types. Theoretical Computer Science, 342(1):3–27, [JV04] Patricia Johann and Janis Voigtländer. Free
2005. theorems in the presence of seq. In POPL’04,
[Acz77] Peter Aczel. The strength of Martin-Löf’s intuition- pages 99–110. ACM Press, 2004.
istic type theory with one universe. In Proceedings of [MFP91] E. Meijer, M. Fokkinga, and R. Paterson. Functional
Symposia in Mathematical Logic, Oulu, 1974, and programming with bananas, lenses, envelopes and
Helsinki, 1975, pages 1–32, University of Helsinki, barbed wire. In FPCA’91, volume 523 of LNCS,
Department of Philosophy, 1977. pages 124–144. Springer-Verlag, 1991.
[BB91] Marek A. Bednarczyk and Andrzej M. Borzyszkowski. [MTHM97] Robin Milner, Mads Tofte, Robert Harper, and
Cpo’s do not form a cpo and yet recursion works. David MacQueen. The Definition of Standard ML
In VDM ’91, volume 551 of LNCS, pages 268–278. (Revised). MIT Press, 1997.
Springer-Verlag, 1991.
[PJ03] Simon Peyton Jones, editor. Haskell 98 Language
[BdBH+ 91] R.C. Backhouse, P.J. de Bruin, P. Hoogendijk, and Libraries, The Revised Report. Cambridge
G. Malcolm, T.S. Voermans, and J.C.S.P. van der University Press, 2003.
Woude. Relational catamorphisms. In Constructing
Programs from Specifications, pages 287–318. [Pri02] Hilary A. Priestley. Ordered sets and complete
North-Holland, 1991. lattices, a primer for computer science. In Algebraic
and Coalgebraic Methods in the Mathematics of
[BdM96] Richard Bird and Oege de Moor. Algebra of Program Construction, volume 2297 of LNCS,
Programming. Prentice Hall, 1996. chapter 2, pages 21–78. Springer-Verlag, 2002.
[Bee82] M. Beeson. Recursive models for constructive set [Rey83] John C. Reynolds. Types, abstraction and para-
theories. Annals of Mathematical Logic, 23:127–178, metric polymorphism. In Information Processing
1982. 83, pages 513–523. Elsevier, 1983.
[Bli87] Andrzej Blikle. MetaSoft Primer, Towards a [Rey84] John C. Reynolds. Polymorphism is not set-
Metalanguage for Applied Denotational Semantics, theoretic. In Semantics of Data Types, volume 173
volume 288 of LNCS. Springer-Verlag, 1987. of LNCS, pages 145–156. Springer-Verlag, 1984.
[BT83] Andrzej Blikle and Andrzej Tarlecki. Naive [Sco76] Dana Scott. Data types as lattices. SIAM Journal
denotational semantics. In Information Processing of Computing, 5(3):522–587, 1976.
83, pages 345–355. North-Holland, 1983.
[Smi84] Jan Smith. An interpretation of Martin-Löf’s type
[Dan05] Nils Anders Danielsson. Personal web page, theory in a type-free theory of propositions. Journal
available at http://www.cs.chalmers.se/~nad/, of Symbolic Logic, 49(3):730–753, 1984.
2005.
[Tur96] David Turner. Elementary strong functional
[Dij76] Edsger W. Dijkstra. A Discipline of Programming. programming. In FPLE’95, volume 1022 of LNCS,
Prentice Hall, 1976. pages 1–13. Springer-Verlag, 1996.
[DJ04] Nils Anders Danielsson and Patrik Jansson. Chasing [Wad89] Philip Wadler. Theorems for free! In FPCA’89,
bottoms, a case study in program verification in pages 347–359. ACM Press, 1989.
the presence of partial and infinite values. In MPC
2004, volume 3125 of LNCS, pages 85–109. Springer-
Verlag, 2004.
[Dyb85] Peter Dybjer. Program verification in a logical
theory of constructions. In FPCA’85, volume
201 of LNCS, pages 334–349. Springer-Verlag,
1985. Appears in revised form as Programming
Methodology Group Report 26, University of
Göteborg and Chalmers University of Technology,
1986.
[Dyb97] Peter Dybjer. Representing inductively defined
sets by wellorderings in Martin-Löf’s type theory.
Theoretical Computer Science, 176:329–335, 1997.
[FM91] Maarten M Fokkinga and Erik Meijer. Program
calculation properties of continuous algebras. Tech-
nical Report CS-R9104, Centre for Mathematics
and Computer Science, Amsterdam, The Nether-
lands, 1991.
[Fri75] Harvey Friedman. Equality between functionals.
In Logic Colloquium: Symposium on Logic held at
Boston, 1972-73, number 453 in Lecture Notes in
Mathematics, pages 22–37. Springer, 1975.
[Hal87] Lars Hallnäs. An intensional characterization of the
largest bisimulation. Theoretical Computer Science,
53(2–3):335–343, 1987.
[HG01] Graham Hutton and Jeremy Gibbons. The generic
approximation lemma. Information Processing

You might also like