Commit a33c0e8f by Nicola Botta

### Initial.

parent 0ed2486b
 % -*-Latex-*- %if False > module About > import Syntax.PreorderReasoning import LexerFriendlyReasoning -- not yet working as intended > infix 6 <=> > %default total > %auto_implicits off > %access public export > Domain : {A, B : Type} -> (A -> B) -> Type > Domain {A} f = A %endif \section{Introduction} \label{section:about} This paper is about \emph{extensional equality preservation} in dependently typed languages like Idris~\citep{idrisbook}, % idristutorial, Agda~\citep{norell2007thesis} and Coq~\citep{CoqProofAssistant_8_11} that implement %some version of Martin-Löf's intensional type theory \citep{martinlof1984}. % , nordstrom1990programming % %% We present our arguments in Idris but the results can be translated to %% other implementations easily. We discuss Idris code but the results could be translated to other languages. % Extensional equality is a property of functions, stating that they are pointwise equal'': % %In Idris, it can be expressed as %TR: Unfortunately doesn't typecheck without {A} ... > (<=>) : {A, B : Type} -> (A -> B) -> (A -> B) -> Type > (<=>) {A} f g = (x : A) -> f x = g x Note that the definition of extensional equality |(<=>)| depends on another equality |(=)|. %*PJ: Perhaps remark that it can be defined for dependent functions as well. % In Agda: (formulation from \citep{DBLP:journals/jfp/AbelCDTW20}) % postulate ext : ∀ {l l'} {A : Set l} {B : A → Set l'} {f g : (a : A) → B a} → % (∀ (a : A) → f a ≡ g a) → f ≡ g % ext follows from univalence and can be used in type theories that assume UIP (uniqueness of identity proofs) \paragraph*{Different flavours of equality.}%\hfill % \begin{quote} All animals are equal, but some animals are more equal than others'' [Animal Farm, Orwell (1946)] \end{quote} There are several kinds of equality'' relevant for programming. % %{ %format -> = "\rightarrow" Programming languages usually offer a Boolean equality check operator and in Idris it is written |(==)|, has type |{A : Type} -> Eq A => A -> A -> Bool| and is packaged in the interface |Eq|. %} % This is an ad-hoc'' equality, computing whatever the programmer supplies as an implementation. % This paper is not about value level Boolean equality. On the type level, the dependently typed languages we consider in this paper provide a notion of \emph{intensional equality}, also referred to as an equality type'', which is an inductively defined family of types, usually written infix: |(a=b) : Type| for |a:A| and |b:B|. It has just one constructor |Refl : a=a|. % The resulting notion is not as boring as it may look at first. We have |Refl:a=b| not only if |a| and |b| are identical, but also if they \emph{reduce} to identical expressions. Builtin reduction rules normally include alpha-conversion (capture-free renaming of bound variables), beta-reduction (using substitution) and eta-reduction: |f = \x=>f x|. % So, for example, we have |Refl: id x = x|. % Furthermore, user-defined equations are also used for reduction. % A typical example is addition of natural numbers: with |+| defined by pattern matching on the first argument, we have e.g. |Refl:1+1=2|. However, while for a variable |n:Nat| we have |Refl : 0+n = n|, we do not have |Refl: n+0=n|. One very useful property of intensional equality is that it is a congruence with respect to any function. % In other words, all functions preserve intensional equality. % The proof uses pattern matching, which is straightforward here because |Refl| is the only constructor: % < cong : {A, B : Type} -> {f : A -> B} -> {a, a' : A} -> a = a' -> f a = f a' < cong Refl = Refl %if False > checkClaim : (n : Nat) -> 0+n = n > checkClaim n = Refl < failClaim : (n : Nat) -> n+0 = n < failClaim n = Refl %endif % In a similar way, one can prove that |(=)| is an equivalence relation: Reflexivity is directly implemented by |Refl|, while symmetry and transitivity can be proven by pattern matching. \paragraph*{Extensional equality.} As one would expect, extensional equality is an equivalence relation > reflEE : {A, B : Type} -> {f : A -> B} -> f <=> f > symEE : {A, B : Type} -> {f, g : A -> B} -> f <=> g -> g <=> f > transEE : {A, B : Type} -> {f, g, h : A -> B} -> f <=> g -> g <=> h -> f <=> h > > reflEE = \x => Refl > symEE p = \x => sym (p x) > transEE p q = \x => trans (p x) (q x) In general, we can lift any (type-valued) binary relation on a type |B| to a binary relation on function types with co-domain |B|. % % \REMARK{Nicola}{As the type of |extify| is now |BinRel B -> BinRel % (A -> B)|, the name of the function and the name |eqB| in its % implementation are perhaps not appropriate? |BinRel| also should % perhaps be called |EndoRel|? Or just |Rel : Type -> Type -> Type| with % |Rel A B = A -> B -> Type| and then |extify : Rel B B -> Rel (A -> B) % (A -> B)|? Perhaps we can get rid of |BinRel| altogether (it is not % used in the rest of the paper) and simply write |extify : {A, B : % Type} -> (B -> B -> Type) -> ((A -> B) -> (A -> B) -> Type|? I am % surprised that |extify| can be applied to |(=) : A -> B -> Type|!} > extify : {A, B : Type} -> (B->B->Type) -> ((A->B)->(A->B)->Type) > extify {A} relB f g = (a : A) -> relB (f a) (g a) The |extify| combinator maps equivalence relations to equivalence relations. % Using it we can redefine |(<=>) = extify (=)| and we can easily continue to quantify over more arguments: |(<==>) = extify (<=>)|, etc. % In this paper our main focus is equality on functions, and we will explore in some detail the relationship between |f=g| and |f<=>g|. % In Martin-Löf's intensional type theory, and thus in Idris, extensional equality is strictly weaker than intensional equality. % More concretely, we can implement > IEqImplEE : {A, B : Type} -> (f, g : A -> B) -> f = g -> f <=> g > IEqImplEE f f Refl = \ x => Refl but not the converse, normally referred to as \emph{function extensionality}: > EEqImplIE : {A, B : Type} -> (f, g : A -> B) -> f <=> g -> f = g -- not implementable When working with functions, extensional equality is often the notion of interest and libraries of formalized mathematics typically provide definitions like |<=>| and basic results like |IEqImplEE|, see for example |homot| and |eqtohomot| in Part A of the UniMath \citep{UniMath} foundations or |eqfun| in Coq \citep{CoqProofAssistant_8_11}. In reasoning about generic programs in the style of the Algebra of Programming \citep{DBLP:books/daglib/0096998,mu2009algebra} and, more generally, in pen and paper proofs, the principle of function extensionality is often taken for granted. \paragraph*{EE preservation.} Preservation of extensional equality is a property of higher order functions: we say that, for fixed, non-function types |A|, |B|, |C| and |D|, a function |h : (A -> B) -> (C -> D)| preserves extensional equality (in one argument) if |f <=> g| implies |h f <=> h g|. Higher order functions are a distinguished trait of functional programming languages \citep{bird2014thinking} and many well known function combinators can be shown to preserve extensional equality. % For example the arrow-function |map| for |Identity|, |List|, |Maybe| and for many other polymorphic data types preserve extensional equality. % Similarly, if |h| takes two function arguments it preserves extensional equality (in two arguments) if |f1 <=> g1| and |f2 <=> g2| implies |h f1 f2 <=> h g1 g2|, etc. %PJ: See notesTR/NonExamples.lidr for some analysis of this. % To illustrate the Idris notation for equational reasoning we show the lemma |compPresEE| proving that function composition satisfies the two-argument version of extensional equality preservation: > compPresEE : {A, B, C : Type} -> {g, g' : B -> C} -> {f, f' : A -> B} -> > g <=> g' -> f <=> f' -> g . f <=> g' . f' > compPresEE {g} {g'} {f} {f'} gExtEq fExtEq x = > ( (g . f) x ) ={ Refl }= > ( g (f x) ) ={ cong (fExtEq x) }= > ( g (f' x) ) ={ gExtEq (f' x) }= > ( g' (f' x) ) ={ Refl }= > ( (g' . f') x ) QED The right hand side is a chain of equal expressions connected by the |={| proofs |}=| of the individual steps within special braces and ending in |QED|, see Preorder reasoning'' in \citep{idrisreference,idristutorial}. % The steps with |Refl| are just for human readability, they could be omitted as far as Idris is concerned. % Note that the proof steps are at the level of intensional equality which all functions preserve as witnessed by |cong|. So one can often use |cong| in steps where an outer context is unchanged (like |g| in this example). % A special case of a two-argument version of |cong| shows that composition (like all functions) preserves intensional equality: > compPresIE : {A, B, C : Type} -> {g, g' : B -> C} -> {f, f' : A -> B} -> > g = g' -> f = f' -> g . f = g' . f' > compPresIE Refl Refl = Refl Note that the strengths'' of the two equality preservation lemmas are not comparable: |compPresIE| proves a stronger conclusion, but from stronger assumptions. \paragraph*{ADTs and equality preservation.} Abstract data types are often specified (e.g., via Idris \emph{interfaces} or Agda \emph{records}) in terms of higher order functions. % Typical examples are, beside the already mentioned |map| for functors, bind and Kleisli composition (see section \ref{section:example}) for monads. % This paper is also about ADTs and generic programming. % More specifically, we show how to exploit the notion of extensional equality preservation to inform the design of ADTs for generic programming and embedded domain-specific languages (DSL). % This is exemplified in sections \ref{section:functors} and \ref{section:monads} for ADTs for functors and monads but we conjecture that other abstract data types, e.g. for applicatives and arrows, could also profit from a design informed by the notion of preservation of extensional equality. Thus, our work can also be seen as a contribution to the discussion on verified ADTs initiated by Nicholas Drozd on \href{https://groups.google.com/forum/#!topic/idris-lang/VZVpi-QUyUc}{idris-lang}. % A caveat is perhaps in place: the discussion on ADTs for functors and monads in sections sections \ref{section:functors} and \ref{section:monads} is not meant to answer the question of what verified interfaces should look like''. Our aim is to demonstrate that, like preservation of identity functions or preservation of composition, preservation of extensional equality is a useful principle for ADT design. \paragraph*{What this paper is not about.} Before turning to a first example, let us spend a few words on what this paper is \emph{not} about. % It is not intended as a contribution to the theoretical study of the equality type in intensional type theory or the algorithmic content of the function extensionality principle. %|EEqImplIE| %% TR: The fact ... is by no means new.'' isn't good. I copied and %% the question of ... in this context'' to the next sentence %% %The fact that |EEqImplIE| is not provable in Martin-Löf's intensional %type theory and the question of how to deal with extensional concepts %in this context are by no means new. % The equality type in intensional type theory and the question of how to deal with extensional concepts in this context has been the subject of important research for the last thirty years. % Since Hofmann's seminal work \citep{hofmann1995extensional}, setoids have been the established, but also often dreaded (who coined the expression \emph{setoid hell''}?) means to deal with extensional concepts in intensional type theory, see also section \ref{section:relatedwork}. % Eventually, the study of Martin-Löf's equality type has lead to the development of Homotopy Type Theory and Voevodsky's Univalent Foundations program \citep{DBLP:books/daglib/0067012,DBLP:conf/lics/HofmannS94,hottbook}. % Univalence and recent developments in \emph{Cubical Type Theory} \citep{cohen2016cubical} promise to finally provide developers with a computational version of function extensionality. %% Tim/Nuria: new paragraph? %%\paragraph*{What this paper is about.} % This paper is a contribution towards \emph{pragmatic} verified generic % programming. It might become obsolete when fully computational notions % of function extensionality will become available in mainstream % programming. This paper is a contribution towards \emph{pragmatic} verified generic programming. In this sense it might become obsolete when fully computational notions of function extensionality will become available in mainstream programming. % However, from a more abstract mathematical perspective, there are good reasons to not use axioms that are stronger than necessary. % For example, there are interesting models of type theory that refute function extensionality \citep{streicher1993investigations, vanGlehn_2015, 10.1145/3018610.3018620}, and results that do not rely on it can be interpreted in these models. % The paper has been generated from literate Idris files. % These can be type-checked with Idris 1.3.2 and are available at \url{https://gitlab.pik-potsdam.de/botta/papers}. %, see \texttt{README.md} in the paper's folder. % In the next section we present a motivating example from monadic dynamical systems, in section~\ref{section:functors} we explore extensional equality preservation for functors and in section \ref{section:monads} for monads. % We continue with dynamical systems applications in section~\ref{section:applications} and finish with related work (section~\ref{section:relatedwork}) and conclusions (section~\ref{section:conclusions}).
 % -*-Latex-*- %if False > module Appendix > import Syntax.PreorderReasoning > import Data.List > import About > import Functors > import Monads > import Applications > %default total > %auto_implicits off > %access public export %endif \appendix \label{section:appendix}