Abstract
For the average programmer, adjunctions are (if at all known) more respected than loved. At best, they are regarded as an algebraic device of theoretical interest only, not useful in common practice.
This paper is aimed at showing the opposite: that adjunctions underlie most of the work we do as programmers, in particular those using the functional paradigm. However, functions alone are not sufficient to express the whole spectrum of programming, with its dichotomy between specifications—what is (often vaguely) required—and implementations—how what is required is (hopefully well) implemented. For this, one needs to extend functions to relations.
Inspired by the pioneering work of Ralf Hinze on “adjoint (un)folds”, the core of the so-called (relational) Algebra of Programming is shown in this paper to arise from adjunctions. Moreover, the paper also shows how to calculate recursive programs from specifications expressed by Galois connections—a special kind of adjunction.
Because Galois connections are easier to understand than adjunctions in general, the paper adopts a tutorial style, starting from the former and leading to the latter (a path usually not followed in the literature). The main aim is to reconcile the functional programming community with a concept that is central to software design as a whole, but rarely accepted as such.
“(...) and Jim Thatcher proposed the name ADJ as a (terrible) pun on the title of the book that we had planned to write (...) [recalling] that adjointness is a very important concept in category theory (...)”
— Joseph A. Goguen, Memories of ADJ, EATCS nr. 36, 1989
Access this chapter
Tax calculation will be finalised at checkout
Purchases are for personal use only
Notes
- 1.
The reader may wonder how (6) fits in the frame of (4). To see this, let us write (6) in the uncurried format: \((\textsf{length}\; ys , ys )\;((\leqslant ) \times (\sqsubseteq ))\;( n , xs )~\Leftrightarrow ~ ys \sqsubseteq \widehat{\textsf{take}}\;( n , xs )\) where, in general, \(\widehat{ g }\;( a , b )\mathrel {=} g \; a \; b \). Thus \( f \; x \mathrel {=}(\textsf{length}\; x , x )\), \( g \mathrel {=}\widehat{\textsf{take}}\) and the product ordering has the expected relational meaning, which in general is: \(( x , y )\;( R \times S )\;( a , b )~\Leftrightarrow ~ x \; R \; a \mathrel {\wedge } y \; S \; b \).
- 2.
The question also applies to \( ys \sqsubseteq []~\Leftrightarrow ~ ys \mathrel {=}[]\) which was taken for granted above.
- 3.
Recall that functors are available in Haskell via \( fmap \), exported by the \( Functor \) class. As is well known, properties \(\textsf{F} \;{id}\mathrel {=}{id}\) and \(\textsf{F} \;( f \mathbin {\cdot } g )\mathrel {=}(\textsf{F} \; f ) \mathbin {\cdot } (\textsf{F} \; g )\) hold.
- 4.
- 5.
Notation \(\textsf{P} \; B \) means the powerset of \( B \), i.e. the set of all subsets of \( B \). Also note that we write \( b \; R \; a \) to express \(( b , a )\;\mathbin \in \; R \), keeping with the tradition of using infix notation in relational facts, e.g. \( a \leqslant b \) instead of \(( a , b )\;\mathbin \in \;(\leqslant )\) and so on. In this vein, relation composition is expressed by \( b \;( S \mathbin {\cdot } R )\; a ~\Leftrightarrow ~\mathopen {\langle }\exists \ c \ :\,\!:\ b \; S \; c \mathrel {\wedge } c \; R \; a \mathclose {\rangle }\).
- 6.
Interestingly, the usual presentation \( y \mathrel {=} f ( x )\) of functions in maths textbooks is relational, not strictly functional.
- 7.
Note that \(\textsf{P} \) is not a relational functor (in \({\textbf{R}}\)) but rather another way of expressing relations by functions in \({\textbf{S}}\). It is often referred to as the existential image functor [4]. Interestingly, (30) captures the way the so-called navigation style of Alloy [12] works, enabling an (essentially) functional execution of its relational core.
- 8.
This is the way relational specifications are handled in [4], for instance.
- 9.
For more details about this monad and how to calculate with it please see e.g. [18].
- 10.
In the sequel we adopt the usual shortcut for functor composition, e.g. \(\textsf{M} \;\textsf{L} \) instead of \(\textsf{M} \mathbin {\cdot } \textsf{L} \) and so on.
- 11.
- 12.
These facts are actually instances of a more general result: coproducts generalize to so-called colimits and these are preserved by left adjoints [14].
- 13.
The fact that we use the same symbol to order relations and order powersets should not be a problem, as types disambiguate its use.
- 14.
Self-duality in \({\textbf{R}}\) arises from isomorphism \(\textsf{P} \; X \cong {\textrm{2}}^{ X }\) (“sets are predicates”) in \({\textbf{S}}\). By this and uncurrying, \( A \rightarrow \textsf{P} \; B \cong {\textrm{2}}^{ A \times B }\). Since \( A \times B \cong B \times A \), we can go in reverse order and obtain \( B \rightarrow \textsf{P} \; A \), etc.
- 15.
Following a widely adopted convention [4] to save text, we denote “relations that are functions” by lowercase letters.
- 16.
- 17.
Such \(\textsf{F} \)-algebra morphisms are often called \(\textsf{F} \)-homomorphisms. Note the overloading of \( f \) in , a \(\textsf{F} \)-algebra morphism; and \( f \) in (47), a function between the corresponding carriers.
- 18.
This is known as the Lambek lemma [4].
- 19.
Definite article because it is unique.
- 20.
In spite of its elementary nature, the for-loop combinator is very useful in programming, see e.g. [8, 19]. The unfolding of (49) down to the given pointwise definition is routine work in algebra of programming practice, see e.g. [18]. Starting from (48), it mainly uses the laws of the \((\mathbin {+})\mathbin \dashv \nabla \) adjunction.
- 21.
- 22.
- 23.
- 24.
Note that the left diagram lives in \({\textbf{R}}\) while the right one lives in \({\textbf{S}}\).
References
Backhouse, K., Backhouse, R.C.: Safety of abstract interpretations for free, via logical relations and Galois connections. SCP 15(1–2), 153–196 (2004)
Backhouse, R.C.: Mathematics of Program Construction, p. 608. University of Nottingham. Unpublished Book Draft (2004)
Backhouse, R.C., de Bruin, P., Hoogendijk, P., Malcolm, G., Voermans, T.S., van der Woude, J.: Polynomial relators. In: Nivat, M., Rattray, C.S., Rus, T., Scollo, G. (eds.) Proceedings of the 2nd Conference on Algebraic Methodology and Software Technology, AMAST 1991, pp. 303–326. Springer, Heidelberg (1991). Workshops in Computing (1992)
Bird, R., de Moor, O.: Algebra of Programming. Prentice-Hall, Upper Saddle River (1997)
Boisseau, G., Gibbons, J.: What you Needa know about Yoneda: profunctor optics and the Yoneda lemma (functional pearl). Proc. ACM Program. Lang. 2(ICFP), 84:1–84:27 (2018)
Burstall, R., Lampson, B.: A Kernel language for abstract data types and modules. In: Kahn, G., MacQueen, D.B., Plotkin, G. (eds.) SDT 1984. LNCS, vol. 173, pp. 1–50. Springer, Heidelberg (1984). https://doi.org/10.1007/3-540-13346-1_1
Burstall, R.M., Goguen, J.A.: Algebras, theories and freeness. Technical report CSR-101-82, University of Edinburgh, February 1982
Danvy, O.: Folding left and right matters: direct style, accumulators, and continuations. J. Funct. Program. 33, e2 (2023)
Gibbons, J., Hinze, R.: Just do it: simple monadic equational reasoning. In: Proceedings of the 16th ACM SIGPLAN International Conference on Functional Programming, ICFP 2011, pp. 2–14. ACM, New York (2011)
Goguen, J.A., Burstall, R.M.: Institutions: abstract model theory for specification and programming. J. ACM 39(1), 95–146 (1992)
Hinze, R.: Adjoint folds and unfolds – an extended study. SCP 78(11), 2108–2159 (2013)
Jackson, D.: Software Abstractions: Logic, Language, and Analysis. The MIT Press, Cambridge (2012). Revised edition, ISBN 0-262-01715-2
Macedo, H.D., Oliveira, J.N.: Typing linear algebra: a biproduct-oriented approach. SCP 78(11), 2160–2191 (2013)
Mac Lane, S.: Categories for the Working Mathematician. GTM, vol. 5. Springer, New York (1978). https://doi.org/10.1007/978-1-4757-4721-8
Moggi, E.: Notions of computation and monads. Inf. Comput. 93(1), 55–92 (1991)
Mu, S.-C., Oliveira, J.N.: Programming from Galois connections. In: de Swart, H. (ed.) RAMICS 2011. LNCS, vol. 6663, pp. 294–313. Springer, Heidelberg (2011). https://doi.org/10.1007/978-3-642-21070-9_22
Oliveira, J.N.: Biproducts of Galois connections. Presentation at the IFIP WG 2.1 #79 Meeting, Otterlo, NL, January 2019
Oliveira, J.N.: Program Design by Calculation (2021). Unpublished book draft, February 2021. Informatics Dept., U. Minho (pdf)
Oliveira, J.N.: A note on the under-appreciated for-loop. Technical report TR-HASLab:01:2020 (2020). (pdf), HASLab/U.Minho and INESC TEC
Oliveira, J.N.: On the power of adjoint recursion. Presentation at the IFIP WG 2.1 #06 Meeting (Online), October 2021
Silva, P.F., Oliveira, J.N.: ‘Galculator’: functional prototype of a Galois-connection based proof assistant. In: PPDP 2008, pp. 44–55. ACM (2008)
Turner, D.A.: Elementary strong functional programming. In: Hartel, P.H., Plasmeijer, R. (eds.) FPLE 1995. LNCS, vol. 1022, pp. 1–13. Springer, Heidelberg (1995). https://doi.org/10.1007/3-540-60675-0_35
Wadler, P.L.: Theorems for free! In: 4th International Symposium on Functional Programming Languages and Computer Architecture, London, pp. 347–359. ACM, September 1989
Wadler, P.L.: Comprehending monads. In: Proceedings of the 1990 ACM Conference on Lisp and Functional Programming, Nice, France (1990)
Winskel, G.: The Formal Semantics of Programming Languages: An Introduction. MIT Press, Cambridge (1993)
Yang, Z., Wu, N.: Fantastic morphisms and where to find them - a guide to recursion schemes. In: MPC 2022. LNCS, vol. 13544, pp. 222–267. Springer, Cham (2022)
Acknowledgments
The author wishes to thank the organizers of WADT’22 for inviting him to give the talk which led to this paper. His work is financed by National Funds through the FCT - Fundação para a Ciência e a Tecnologia, I.P. (Portuguese Foundation for Science and Technology) within the IBEX project, with reference PTDC/CCI-COM/4280/2021.
Author information
Authors and Affiliations
Corresponding author
Editor information
Editors and Affiliations
A Properties of Adjunctions and Monads
A Properties of Adjunctions and Monads
Corollaries of \( k \mathrel {=}\lceil f \rceil ~\Leftrightarrow ~\epsilon \mathbin {\cdot } \textsf{L} \; k \mathrel {=} f \) (17)
reflection:
that is,
cancellation:
fusion:
absorption:
naturality:
closed definition:
functor:
isomorphism:
Dual corollaries of \( k \mathrel {=}\lfloor f \rfloor ~\Leftrightarrow ~\textsf{R} \; k \mathbin {\cdot } \eta \mathrel {=} f \) (19)
reflection:
that is,
cancellation:
fusion:
absorption:
naturality:
closed definition:
functor
cancellation (corollary):
Monads. Proof of (32):
Proof of (33):
Proof of (37):
Rights and permissions
Copyright information
© 2023 Springer Nature Switzerland AG
About this paper
Cite this paper
Oliveira, J.N. (2023). Why Adjunctions Matter—A Functional Programmer Perspective. In: Madeira, A., Martins, M.A. (eds) Recent Trends in Algebraic Development Techniques. WADT 2022. Lecture Notes in Computer Science, vol 13710. Springer, Cham. https://doi.org/10.1007/978-3-031-43345-0_2
Download citation
DOI: https://doi.org/10.1007/978-3-031-43345-0_2
Published:
Publisher Name: Springer, Cham
Print ISBN: 978-3-031-43344-3
Online ISBN: 978-3-031-43345-0
eBook Packages: Computer ScienceComputer Science (R0)