├── .gitignore ├── Sf.bib ├── README.md ├── Preface.lagda ├── makefile ├── MorePropositions.lagda ├── Sf.lagda ├── MoreInd.lagda ├── ProofObjects.lagda ├── MoreAgda.lagda ├── proof.sty ├── SfLib.lagda ├── InductionProofs.lagda ├── Propositions.lagda ├── Logic.lagda ├── Lists.lagda ├── Poly.lagda ├── Basics.lagda └── natbib.bst /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.agdai 3 | *.out -------------------------------------------------------------------------------- /Sf.bib: -------------------------------------------------------------------------------- 1 | @misc{Wiki, 2 | author = {{Agda Development Team}}, 3 | title = {{The Agda Wiki website}}, 4 | howpublished = {wiki Agda}, 5 | year = {2014} 6 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Software Foundations 2 | ==================== 3 | 4 | A translation of Pierce's Coq book Software foundations to Agda. 5 | This is just an adaptation of the previous cited book. -------------------------------------------------------------------------------- /Preface.lagda: -------------------------------------------------------------------------------- 1 | %if False 2 | \begin{code} 3 | module Preface where 4 | \end{code} 5 | %endif 6 | 7 | \chapter*{Preface} 8 | 9 | \section*{Welcome} 10 | 11 | This electronic book is a Agda version of Pierce's Coq book named Software Foundations. 12 | 13 | \section*{Overview} 14 | 15 | ... 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | default: sf 2 | 3 | sf: 4 | lhs2TeX --agda Sf.lagda > Sf.tex 5 | pdflatex Sf.tex 6 | bibtex Sf.aux 7 | pdflatex Sf.tex 8 | pdflatex Sf.tex 9 | clean: 10 | rm *.tex 11 | rm *.pdf 12 | rm *.aux 13 | rm *.log 14 | rm *.ptb 15 | rm *.toc 16 | rm *.out 17 | rm *.bbl 18 | rm *.blg 19 | rm *.agdai 20 | view: sf 21 | evince Sf.pdf & 22 | -------------------------------------------------------------------------------- /MorePropositions.lagda: -------------------------------------------------------------------------------- 1 | \chapter{More about Propositions and Evidence} 2 | 3 | %if False 4 | \begin{code} 5 | module MorePropositions where 6 | 7 | open import Basics 8 | open import Poly 9 | open import Propositions 10 | \end{code} 11 | %endif 12 | 13 | \section{Relations} 14 | 15 | A proposition parameterized by a number (such as |Ev| or |Beautiful|) can be thought of as a property --- 16 | i.e., it defines a subset of |Nat|, namely those numbers for which the proposition is provable. In the same 17 | way, a two-argument proposition can be thought of as a relation --- i.e., it defines a set of pairs for which 18 | the proposition is provable. 19 | 20 | One useful example is the ``less than or equal to'' relation on numbers. 21 | 22 | The following definition should be fairly intuitive. It says that there are two ways to give evidence that one 23 | number is less than or equal to another: either observe that they are the same number, or give evidence that 24 | the first is less than or equal to the predecessor of the second. 25 | \begin{code} 26 | data _<=_ : Nat -> Nat -> Set where 27 | len : forall n -> n <= n 28 | les : forall n m -> n <= m -> n <= suc m 29 | \end{code} 30 | Proofs of facts about |<=| using the constructors |len| and |les| follow the same patterns as proofs 31 | about properties, like |Ev| in the previous chapter. We can apply the constructors to prove |<=| goals 32 | (e.g., to show that |3<=3| or |3<=6|), and we can use pattern matching to extract information from |<=| 33 | hypotheses in the context (e.g., to prove that |(2 <= 1) -> 2+2==5|.) 34 | 35 | The "strictly less than" relation |n < m| can now be defined in terms of |n <= m|: 36 | \begin{code} 37 | _<_ : Nat -> Nat -> Set 38 | n < m = suc n <= m 39 | \end{code} 40 | 41 | \begin{exe} 42 | Prove the following fact: 43 | \begin{spec} 44 | leTrans : forall {m n o} -> m <= n -> n <= o -> m <= o 45 | leTrans = (HOLE GAP 0) 46 | \end{spec} 47 | \end{exe} 48 | 49 | \begin{exe} 50 | Prove the following fact: 51 | \begin{spec} 52 | zeroLeN : forall n -> 0 <= n 53 | zeroLeN = (HOLE GAP 0) 54 | \end{spec} 55 | \end{exe} 56 | 57 | \begin{exe} 58 | Prove the following fact: 59 | \begin{spec} 60 | nLeMSnleSm : forall n m -> n <= m -> suc n <= suc m 61 | nLeMSnleSm = (HOLE GAP 0) 62 | \end{spec} 63 | \end{exe} 64 | 65 | \begin{exe} 66 | Prove the following fact: 67 | \begin{spec} 68 | snLeSmNLeM : forall n m -> suc n <= suc m -> n <= m 69 | snLeSmNLeM = (HOLE GAP 0) 70 | \end{spec} 71 | \end{exe} 72 | 73 | \begin{exe} 74 | Prove the following fact: 75 | \begin{spec} 76 | lePlusL : forall a b -> a <= a + b 77 | lePlusL = (HOLE GAP 0) 78 | \end{spec} 79 | \end{exe} 80 | 81 | \begin{exe} 82 | Prove the following fact: 83 | \begin{spec} 84 | plusLt : forall n1 n2 m -> n1 + n2 < m -> n1 < m -> n2 < m 85 | plusLt = (HOLE GAP 0) 86 | \end{spec} 87 | \end{exe} 88 | 89 | \begin{exe} 90 | Prove the following fact: 91 | \begin{spec} 92 | ltsuc : forall n m -> n < m -> n < suc m 93 | ltsuc = (HOLE GAP 0) 94 | \end{spec} 95 | \end{exe} 96 | 97 | \section{Programming with Propositions} 98 | 99 | A proposition is a statement expressing a factual claim, like ``two plus two equals four.'' In Agda, propositions 100 | are written as types. Although we haven't discussed this explicitly, we have already seen numerous examples. 101 | 102 | One important point: Both provable and unprovable claims are perfectly good propositions. Simply being a proposition is one thing; 103 | being provable is something else! Consider these examples: 104 | \begin{spec} 105 | t : 2 + 2 == 4 106 | t = refl 107 | 108 | t' : 2 + 2 == 5 109 | t' = (HOLE GAP 0) -- not provable 110 | \end{spec} 111 | Of course proposition |t'| cannot be provable, because reducing its type we get |4 == 5|, that can't be proved. 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /Sf.lagda: -------------------------------------------------------------------------------- 1 | \documentclass{book} 2 | \usepackage{a4} 3 | \usepackage{palatino} 4 | \usepackage{natbib} 5 | \usepackage{amsmath,amsthm,proof} 6 | \usepackage{amssymb} 7 | \usepackage{amsfonts} 8 | \usepackage{stmaryrd} 9 | \usepackage{upgreek} 10 | \usepackage[pdftex]{hyperref} 11 | \usepackage{url} 12 | 13 | 14 | \DeclareMathAlphabet{\mathkw}{OT1}{cmss}{bx}{n} 15 | 16 | \usepackage{color} 17 | \newcommand{\redFG}[1]{\textcolor[rgb]{0.6,0,0}{#1}} 18 | \newcommand{\greenFG}[1]{\textcolor[rgb]{0,0.4,0}{#1}} 19 | \newcommand{\blueFG}[1]{\textcolor[rgb]{0,0,0.8}{#1}} 20 | \newcommand{\orangeFG}[1]{\textcolor[rgb]{0.8,0.4,0}{#1}} 21 | \newcommand{\purpleFG}[1]{\textcolor[rgb]{0.4,0,0.4}{#1}} 22 | \newcommand{\yellowFG}[1]{\textcolor{yellow}{#1}} 23 | \newcommand{\brownFG}[1]{\textcolor[rgb]{0.5,0.2,0.2}{#1}} 24 | \newcommand{\blackFG}[1]{\textcolor[rgb]{0,0,0}{#1}} 25 | \newcommand{\whiteFG}[1]{\textcolor[rgb]{1,1,1}{#1}} 26 | \newcommand{\yellowBG}[1]{\colorbox[rgb]{1,1,0.2}{#1}} 27 | \newcommand{\brownBG}[1]{\colorbox[rgb]{1.0,0.7,0.4}{#1}} 28 | 29 | \newcommand{\ColourStuff}{ 30 | \newcommand{\red}{\redFG} 31 | \newcommand{\green}{\greenFG} 32 | \newcommand{\blue}{\blueFG} 33 | \newcommand{\orange}{\orangeFG} 34 | \newcommand{\purple}{\purpleFG} 35 | \newcommand{\yellow}{\yellowFG} 36 | \newcommand{\brown}{\brownFG} 37 | \newcommand{\black}{\blackFG} 38 | \newcommand{\white}{\whiteFG} 39 | } 40 | 41 | \newcommand{\MonochromeStuff}{ 42 | \newcommand{\red}{\blackFG} 43 | \newcommand{\green}{\blackFG} 44 | \newcommand{\blue}{\blackFG} 45 | \newcommand{\orange}{\blackFG} 46 | \newcommand{\purple}{\blackFG} 47 | \newcommand{\yellow}{\blackFG} 48 | \newcommand{\brown}{\blackFG} 49 | \newcommand{\black}{\blackFG} 50 | \newcommand{\white}{\blackFG} 51 | } 52 | 53 | \ColourStuff 54 | 55 | 56 | \newcommand{\M}[1]{\mathsf{#1}} 57 | \newcommand{\D}[1]{\blue{\mathsf{#1}}} 58 | \newcommand{\C}[1]{\red{\mathsf{#1}}} 59 | \newcommand{\F}[1]{\green{\mathsf{#1}}} 60 | \newcommand{\V}[1]{\purple{\mathit{#1}}} 61 | \newcommand{\T}[1]{\raisebox{0.02in}{\tiny\green{\textsc{#1}}}} 62 | 63 | \newcommand{\us}[1]{\_\!#1\!\_} 64 | \newtheorem{theorem}{Theorem} 65 | \newtheorem{exe}{Exercise}[chapter] 66 | 67 | %include lhs2TeX.fmt 68 | %include lhs2TeX.sty 69 | %include polycode.fmt 70 | 71 | %subst keyword a = "\mathkw{" a "}" 72 | %subst conid a = "\V{" a "}" 73 | %subst varid a = "\F{" a "}" 74 | 75 | %format -> = "\blue{\rightarrow}" 76 | 77 | \newcommand{\nudge}[1]{\marginpar{\footnotesize #1}} 78 | 79 | %format rewrite = "\mathkw{rewrite}" 80 | %format constructor = "\mathkw{constructor}" 81 | %format Set = "\D{Set}" 82 | %format Ty = "\D{Ty}" 83 | %format iota = "\C{\upiota}" 84 | %format ->> = "\C{\rhd}" 85 | %format <-> = "\leftrightarrow" 86 | %format _<->_ = "\_\!" <-> "\!\_" 87 | %format _/=_ = "\_\!" /= "\!\_" 88 | %format . = "." 89 | %format _->>_ = "\_\!" ->> "\!\_" 90 | %format * = "\C{\times}" 91 | %format :+ = "\F{+}" 92 | %format :* = "\F{*}" 93 | %format _*_ = "\_\!\," * "\,\!\_" 94 | %format _==_ = "\_\!" == "\!\_" 95 | %format Cx = "\D{Cx}" 96 | %format QED = "\D{\Box}" 97 | %format ++ = "\F{++}" 98 | %format <> = "\D{nil}" 99 | %format Em = "\C{\mathcal{E}}" 100 | %format <: = "\D{\in}" 101 | %format _<:_ = "\us{" <: "}" 102 | %format Gam = "\V{\Gamma}" 103 | %format Ren = "\F{Ren}" 104 | %format Sub = "\F{Sub}" 105 | %format Del = "\V{\Delta}" 106 | %format sg = "\V{\sigma}" 107 | %format tau = "\V{\tau}" 108 | %format var = "\C{var}" 109 | %format lam = "\C{lam}" 110 | %format app = "\C{app}" 111 | %format :: = "\!\raisebox{ -0.09in}[0in][0in]{\red{\textsf{`}}\,}" 112 | %format _::_ = _ :: _ 113 | %format ? = "\orange{?}" 114 | %format (HOLE (x) n) = { x } "\!_{" n "}" 115 | %format GAP = "\;" 116 | 117 | \begin{document} 118 | \title{Software Foundations} 119 | \maketitle 120 | \tableofcontents 121 | 122 | %if False 123 | \begin{code} 124 | module Sf where 125 | \end{code} 126 | %endif 127 | 128 | %include Preface.lagda 129 | %include Basics.lagda 130 | %include InductionProofs.lagda 131 | %include Lists.lagda 132 | %include Poly.lagda 133 | %include MoreAgda.lagda 134 | %include Propositions.lagda 135 | %include MorePropositions.lagda 136 | %include Logic.lagda 137 | %include ProofObjects.lagda 138 | %include MoreInd.lagda 139 | %include SfLib.lagda 140 | 141 | \bibliographystyle{natbib} 142 | \bibliography{Sf.bib} 143 | \end{document} 144 | -------------------------------------------------------------------------------- /MoreInd.lagda: -------------------------------------------------------------------------------- 1 | \chapter{More on Induction} 2 | 3 | In the last chapter we introduce more formally the idea of the \textit{Curry-Howard isomorphism}, in which 4 | logical propositions correspond to type constructors. So, to what programming construct correspond mathematical 5 | induction principles? In this chapter, we will wee that induction corresponds to the notion of recursion 6 | in programming languages. 7 | 8 | %if False 9 | \begin{code} 10 | module MoreInd where 11 | 12 | open import Basics renaming (_*_ to _:*_;_+_ to _:+_) 13 | open import Poly 14 | open import Propositions 15 | open import MorePropositions 16 | open import Logic 17 | open import ProofObjects 18 | \end{code} 19 | %endif 20 | 21 | Unlike Coq, Agda does not generate an induction principle for each data type we define. Instead of using induction 22 | or applying a generated induction principle, in Agda we just use recursive functions to express the property we want. 23 | We can even express the induction principle generated by Coq using a simple Agda function. 24 | \begin{code} 25 | natInd : forall (P : Nat -> Set) -> P 0 -> (forall (n : Nat) -> P n -> P (suc n)) -> 26 | forall (n : Nat) -> P n 27 | natInd P p0 IH zero = p0 28 | natInd P p0 IH (suc n) = natInd (\ z -> P (suc z)) (IH zero p0) (\ n1 -> IH (suc n1)) n 29 | \end{code} 30 | With |natInd| defined we can mimic Coq style proofs for natural numbers. Here is an example, were we proceed by induction on |n|: 31 | \begin{spec} 32 | multZeroR : forall (n : Nat) -> n :* 0 == 0 33 | multZeroR n = natInd (HOLE GAP 0) (HOLE GAP 1) (HOLE GAP 2) n 34 | \end{spec} 35 | Since the property that we want to prove is that $\forall n. n * 0 \equiv 0$, |P| parameter corresponds to the property |n :* 0 == 0|, 36 | resulting in: 37 | \begin{spec} 38 | multZeroR : forall (n : Nat) -> n :* 0 == 0 39 | multZeroR n = natInd (\x -> x :* 0 == 0) (HOLE GAP 1) (HOLE GAP 2) n 40 | \end{spec} 41 | The last two holes correpond to the base case and the induction step for this proof, that are trivially solved by Agda's emacs mode auto solver. 42 | The final proof is the following. 43 | \begin{code} 44 | multZeroR : forall (n : Nat) -> n :* 0 == 0 45 | multZeroR n = natInd (\x -> x :* 0 == 0) refl (λ n1 z -> z) n 46 | \end{code} 47 | \begin{exe}[Induction on lists] 48 | Let's remember the list data type definition: 49 | \begin{spec} 50 | data List (A : Set) : Set where 51 | [] : List A 52 | _::_ : A -> List A -> List A 53 | \end{spec} 54 | Define the function |listInd|, the induction principle for lists and use it to prove the following theorem: 55 | \begin{spec} 56 | length-++' : forall (l l' : List A) -> length (l ++ l') == length l + length l' 57 | length-++' = (HOLE GAP 0) 58 | \end{spec} 59 | \end{exe} 60 | \begin{exe}[Induction on enumerated types] 61 | Consider the following data type definition: 62 | \begin{code} 63 | data RGB : Set where 64 | red : RGB 65 | blue : RGB 66 | green : RGB 67 | \end{code} 68 | Define the function |rgbInd|, the induction principle for |RGB| type. 69 | \end{exe} 70 | \begin{exe}[Induction on propositions] 71 | Consider the definition of the following inductive predicate over natural numbers: 72 | \begin{spec} 73 | data Beautiful : Nat -> Set where 74 | b0 : Beautiful 0 75 | b3 : Beautiful 3 76 | b5 : Beautiful 5 77 | bsum : forall {n m} -> Beautiful n -> Beautiful m -> Beautiful (n + m) 78 | \end{spec} 79 | Define the function |beautifulInd|, the induction principle on |Beautiful| and use it to prove that 80 | it is equivalent to the following data type. 81 | \begin{spec} 82 | data Gorgeous : Nat -> Set where 83 | g0 : Gorgeous 0 84 | g3 : forall {n} -> Gorgeous n -> Gorgeous (3 :+ n) 85 | g5 : forall {n} -> Gorgeous n -> Gorgeous (5 :+ n) 86 | \end{spec} 87 | \end{exe} 88 | 89 | \section{The Agda Trusted Computing Base} 90 | 91 | One issue that arises with any automated proof assistant is ``why trust it?'': what if there is a bug 92 | in the implementation that renders all its reasoning suspect? 93 | 94 | While it is impossible to allay such concerns completely, the fact that Agda is based on the Curry-Howard correspondence 95 | gives it a strong foundation. Because propositions are just types and proofs are just terms, checking that an alleged proof 96 | of a proposition is valid just amounts to type-checking the term. Type checkers are relatively small and straightforward 97 | programs, so the ``trusted computing base'' for Agda --- 98 | the part of the code that we have to believe is operating correctly --- is small too. 99 | 100 | What must a typechecker do? Its primary job is to make sure that in each function application the expected and actual 101 | argument types match, that the arms of a match expression are constructor patterns belonging to the inductive type being 102 | matched over and all arms of the match return the same type, and so on. 103 | 104 | There are a few additional wrinkles: 105 | 106 | \begin{itemize} 107 | \item Since Agda types can themselves be expressions, the checker must normalize these (by using the computation rules) before comparing them. 108 | \item The checker must make sure that match expressions are exhaustive. That is, there must be an arm for every possible constructor. 109 | To see why, consider the following alleged proof object: 110 | \begin{spec} 111 | orBugs : forall P Q -> P + Q -> P 112 | orBugs P Q (inl H) = H 113 | \end{spec} 114 | All the types here match correctly, but the match only considers one of the possible constructors for or. Agda's 115 | exhaustiveness check will reject this definition. 116 | \item The checker must make sure that each fix expression terminates. It does this using a syntactic check to 117 | make sure that each recursive call is on a subexpression of the original argument. To see why this is essential, 118 | consider this alleged proof: 119 | \begin{spec} 120 | natEmpty : forall (n : Nat) -> Empty 121 | natEmpty n = natEmpty n 122 | \end{spec} 123 | Again, this is perfectly well-typed, but (fortunately) Agda will reject it, highlighting it as brown in Agda emacs mode. 124 | \end{itemize} 125 | 126 | Note that the soundness of Agda depends only on the correctness of its typechecking engine. 127 | -------------------------------------------------------------------------------- /ProofObjects.lagda: -------------------------------------------------------------------------------- 1 | \chapter{Proof Objects --- Explicit Evidence in Agda} 2 | 3 | We have seen that in Agda the mechanisms used for programming --- inductive data types (like |Nat| or |List|) 4 | and functions over these types --- can be also used for proving properties of these programs, using 5 | inductive propositions (like |Ev| or |_==_|), implication, and universal quantification. 6 | In other proof assistants, like Coq, these mechanisms are quite separate. 7 | 8 | In this chapter we will take a more serious look at the so called ``Curry-Howard Isomophism'', that 9 | states the correspondence between functional programs and proofs. 10 | 11 | %if False 12 | \begin{code} 13 | module ProofObjects where 14 | 15 | open import Basics hiding (_*_) renaming (_+_ to _:+_) 16 | open import Poly 17 | open import Propositions 18 | open import MorePropositions 19 | open import Logic 20 | \end{code} 21 | %endif 22 | 23 | We have already seen the fundamental idea: provability in Agda is represented by concrete evidence. 24 | When we construct the proof of a basic proposition, we are actually building a tree of evidence, 25 | which can be thought of as a data structure. If the proposition is an implication like |A -> B|, 26 | then its proof will be an evidence transformer: a recipe for converting evidence for |A| into 27 | evidence for |B|. So at a fundamental level, proofs are simply programs that manipulate evidence. 28 | 29 | \begin{itemize} 30 | \item[Q.] If evidence is data, what are propositions themselves? 31 | \item[A.] They are types! 32 | \end{itemize} 33 | 34 | Look again at the definition of the beautiful property. 35 | \begin{spec} 36 | data Beautiful : Nat -> Set where 37 | b0 : Beautiful 0 38 | b3 : Beautiful 3 39 | b5 : Beautiful 5 40 | bsum : forall {n m} -> Beautiful n -> Beautiful m -> Beautiful (n + m) 41 | \end{spec} 42 | The trick is to introduce an alternative pronunciation of ``:''. Instead of ``has type'' we can also say ``is a proof of.'' 43 | For example, the second line in the definition of |Beautiful| declares that |b0 : beautiful 0|. Instead of 44 | ``b0 has type beautiful 0,'' we can say that ``b0 is a proof of beautiful 0.'' Similarly for |b3| and |b5|. 45 | This pun between types and propositions (between : as ``has type'' and : as ``is a proof of'' or ``is evidence for'') 46 | is called the \textbf{Curry-Howard correspondence}. It proposes a deep connection between the world of logic and 47 | the world of computation. This can be represented as: 48 | \begin{center} 49 | \begin{tabular}{lcl} 50 | Logic & & Computation\\ 51 | propositions & $\equiv$ & types\\ 52 | proofs & $\equiv$ & data values 53 | \end{tabular} 54 | \end{center} 55 | Many useful insights follow from this connection. To begin with, it gives us a natural interpretation of the type of |bsum| constructor: 56 | \begin{center} 57 | |bsum : forall {n m} -> Beautiful n -> Beautiful m -> Beautiful (n + m)| 58 | \end{center} 59 | This can be read ``|bsum| is a constructor that takes four arguments --- two numbers, |n| and |m|, and two values, of types 60 | |Beautiful n| and |Beautiful m| --- and yields evidence for the proposition |Beautiful (n+m)|.'' 61 | 62 | A proof that eight is beautiful, is just the expression |bsum {3} {5} b3 b5|, as we can represent by the following natural deduction style proof: 63 | \[ 64 | \begin{array}{c} 65 | \infer[(b_{sum})] 66 | {\textit{beautiful }8} 67 | { 68 | \infer[(b_3)] 69 | {\textit{beautiful }3} 70 | {} 71 | & 72 | \infer[(b_5)] 73 | {\textit{beautiful }5} 74 | {} 75 | } 76 | \end{array} 77 | \] 78 | Note that in the expression |bsum {3} {5} b3 b5| we can optionally give the implicit parameters |n| and |m| of |bsum| constructor. 79 | 80 | \section{Quantification, Implications and Functions} 81 | 82 | In Agda there are two sorts of values with arrows in their types: constructors introduced by inductively defined data types, and functions. 83 | Arrows correspond, in the logical side, to the way of give evidence to implications and functions. 84 | Consider the following statement: 85 | \begin{code} 86 | bplus3 : forall (n : Nat) -> Beautiful n -> Beautiful (n :+ 3) 87 | bplus3 n bn = bsum bn b3 88 | \end{code} 89 | What is the proof object corresponding to |bplus3|? 90 | We're looking for an expression whose type is |forall n -> Beautiful n -> Beautiful (n + 3)| --- that is, a function that takes two 91 | arguments (one number and a piece of evidence) and returns a piece of evidence! 92 | 93 | When we view the proposition being proved by |bplus3| as a function type, one aspect of it may seem a little unusual. The second 94 | argument's type, |Beautiful n|, mentions the value of the first argument, |n|. While such dependent types are not commonly found 95 | in ``mainstream'' programming languages, even functional ones like ML or Haskell, they can be useful there too. 96 | 97 | Notice that both implication |->| and quantification |forall| correspond to functions on evidence. In fact, they are really 98 | the same thing: |->| is just a shorthand for a degenerate use of |forall| where there is no dependency, i.e., no need to give 99 | a name to the type on the LHS of the arrow. 100 | 101 | For example, consider this proposition: 102 | 103 | \begin{center} 104 | |bplus3' : forall n (E : Beautiful n) -> Beautiful (n :+ 3)| 105 | \end{center} 106 | 107 | A proof term inhabiting this proposition would be a function with two arguments: a number |n| and some evidence |E| that |n| is beautiful. 108 | But the name |E| for this evidence is not used in the rest of the statement of |bplus3'|, so it's a bit silly to bother making up a name 109 | for it. We could write it like this instead, using the dummy identifier |_| in place of a real name: 110 | 111 | \begin{center} 112 | |bplus3' : forall n (_ : Beautiful n) -> Beautiful (n :+ 3)| 113 | \end{center} 114 | 115 | \section{Giving Explicit Arguments to Lemmas and Hypotheses} 116 | 117 | Sometimes when we want to use a theorem or a hypotheses that has implications or universal quantifiers we need to give 118 | explicit arguments to these parameters. Agda has a efficient term inference mechanism that is able to infer most of 119 | these parameters. Whenever Agda can't infer these parameters, Agda emacs mode will highlight the expression in yellow in 120 | order to indicate that there is some parameter that could not be infered. Consider the next example: 121 | 122 | %if False 123 | \begin{code} 124 | postulate plusComm : forall (a b : Nat) -> a :+ b == b :+ a 125 | \end{code} 126 | %endif 127 | \begin{spec} 128 | plusCommR : forall (a b c d e f: Nat) -> (a :+ b) == (c :+ d) -> (c :+ d) == (e :+ f) -> 129 | (a :+ b) == (e :+ f) 130 | plusCommR a b c = (HOLE GAP 0) 131 | \end{spec} 132 | 133 | Here I'll need a better example for this... 134 | 135 | 136 | -------------------------------------------------------------------------------- /MoreAgda.lagda: -------------------------------------------------------------------------------- 1 | \chapter{More About Agda} 2 | 3 | This chapter introduces some features involving Agda's pattern matching mechanism that, 4 | together, allow us to prove many more theorems about the functional programs we are writing. 5 | 6 | 7 | %if False 8 | \begin{code} 9 | module MoreAgda where 10 | 11 | open import Basics hiding (_*_) 12 | open import Lists hiding (rev; length;snoc) 13 | open import Poly 14 | \end{code} 15 | %endif 16 | 17 | \section{Using Hypothesis and Theorems} 18 | 19 | We often encounter situations where the goal to be proved is exactly the same as some 20 | hypothesis in the context or some previously proved lemma. 21 | \begin{code} 22 | 23 | Eq : {l : Level}(A : Set l) -> A -> A -> Set l 24 | Eq {l} A x y = _==_ {l} {A} x y 25 | 26 | NListEq : List Nat -> List Nat -> Set 27 | NListEq l1 l2 = Eq (List Nat) l1 l2 28 | 29 | Silly1 : (n o m p : Nat) -> Set 30 | Silly1 n o m p = n == m -> t1 -> t2 31 | where 32 | t1 = NListEq (n , o , nil) (n , p , nil) 33 | t2 = NListEq (n , o , nil) (m , p , nil) 34 | 35 | 36 | silly1 : forall (n m o p : Nat) -> Silly1 n o m p 37 | silly1 n m o p nm rewrite nm = id 38 | \end{code} 39 | 40 | 41 | \begin{code} 42 | Hyp : Nat -> Nat -> Set 43 | Hyp o p = forall (q r : Nat) -> q == r -> t q r 44 | where 45 | t : Nat -> Nat -> Set 46 | t q r = NListEq (q , o , nil) (r , p , nil) 47 | 48 | Silly2 : (n m o p : Nat) -> Set 49 | Silly2 n m o p = n == m -> Hyp o p -> t 50 | where 51 | t = NListEq (n , o , nil) (m , p , nil) 52 | 53 | silly2 : forall (n m o p : Nat) -> Silly2 n m o p 54 | silly2 n m o p nm hyp = hyp n m nm 55 | \end{code} 56 | 57 | 58 | \begin{code} 59 | NPairEq : (n m o p : Nat) -> Set 60 | NPairEq n m o p = Eq (Nat * Nat) (n , m) (o , p) 61 | 62 | Hyp2a : Set 63 | Hyp2a = forall (q r : Nat) -> NPairEq q q r r -> NListEq (q , nil) (r , nil) 64 | 65 | Silly2a : Nat -> Nat -> Set 66 | Silly2a n m = NPairEq n n m m -> Hyp2a -> NListEq (n , nil) (m , nil) 67 | 68 | silly2a : forall (n m : Nat) -> Silly2a n m 69 | silly2a .m m refl hyp = refl 70 | \end{code} 71 | 72 | The next is a exercice 73 | 74 | \begin{code} 75 | SillyEx : Set 76 | SillyEx = forall (n : Nat) -> evenb n == True -> oddb (suc n) == True 77 | 78 | sillyEx : SillyEx -> evenb 3 == True -> oddb 4 == True 79 | sillyEx silly = silly (suc (suc (suc zero))) 80 | \end{code} 81 | 82 | \begin{code} 83 | silly3 : forall (n : Nat) -> True == beqNat n 5 -> beqNat (suc (suc n)) 7 == True 84 | silly3 n = sym 85 | \end{code} 86 | 87 | Another exercice. Need revInvolutive property. 88 | 89 | \begin{code} 90 | revExercice1 : forall (l l' : List Nat) -> l == rev l' -> l' == rev l 91 | revExercice1 l l' = {!!} 92 | \end{code} 93 | 94 | These next examples are used to justify the apply with tactic. 95 | 96 | \begin{code} 97 | transEqExample : forall (a b c d e f : Nat) -> NListEq (a , b , nil) (c , d , nil) -> 98 | NListEq (c , d , nil) (e , f , nil) -> 99 | NListEq (a , b , nil) (e , f , nil) 100 | transEqExample a b .a .b .a .b refl refl = refl 101 | \end{code} 102 | 103 | Now, using |trans|. 104 | 105 | \begin{code} 106 | transEqExample' : forall (a b c d e f : Nat) -> NListEq (a , b , nil) (c , d , nil) -> 107 | NListEq (c , d , nil) (e , f , nil) -> 108 | NListEq (a , b , nil) (e , f , nil) 109 | transEqExample' a b c d e f eq1 eq2 = trans eq1 eq2 110 | \end{code} 111 | 112 | \section{Inversion} 113 | 114 | Explanation. Pattern matching and emacs mode rocks. 115 | 116 | \begin{code} 117 | eqAddSuc : forall {n m : Nat} -> suc n == suc m -> n == m 118 | eqAddSuc refl = refl 119 | \end{code} 120 | 121 | \begin{code} 122 | silly4 : forall (n m : Nat) -> NListEq (n , nil) (m , nil) -> n == m 123 | silly4 .m m refl = refl 124 | \end{code} 125 | 126 | \begin{code} 127 | silly5 : forall (n m o : Nat) -> NListEq (n , m , nil) (o , o , nil) -> NListEq (n , nil) (m , nil) 128 | silly5 .o .o o refl = refl 129 | \end{code} 130 | 131 | now starts sillyex1. Need to explain absurd patterns. 132 | 133 | \begin{code} 134 | sillyex1 : forall {l}(A : Set l)(x y z : A)(l j : List A) -> Eq (List A) (x , y , l) (z , j) -> 135 | Eq (List A) (y , l) (x , j) -> 136 | x == y 137 | sillyex1 A .z y z l1 .(y , l1) refl () 138 | \end{code} 139 | 140 | \begin{code} 141 | silly6 : forall (n : Nat) -> suc n == 0 -> 2 + 2 == 5 142 | silly6 n () 143 | 144 | silly7 : forall (n m : Nat) -> True == False -> NListEq (n , nil) (m , nil) 145 | silly7 n m () 146 | \end{code} 147 | 148 | silly ex2 149 | 150 | \begin{code} 151 | sillyex2 : forall {l}{A : Set l}(x y z : A)(l j : List A) -> 152 | Eq (List A) (x , y , l) nil -> 153 | Eq (List A) (y , l) (z , j) -> 154 | x == z 155 | sillyex2 x y z l j () 156 | \end{code} 157 | 158 | \begin{spec} 159 | cong : forall {A B : Set} (f : A -> B){x y : A} -> x == y -> f x == f y 160 | cong f {x} {.x} refl = refl 161 | \end{spec} 162 | 163 | \begin{code} 164 | lengthSnoc' : forall {A : Set}(v : A)(l : List A)(n : Nat) -> 165 | length l == n -> length (snoc v l) == suc n 166 | lengthSnoc' v nil n h1 = cong suc h1 167 | lengthSnoc' v (x , l) zero () 168 | lengthSnoc' v (x , l) (suc n) p = cong suc (lengthSnoc' v l n (eqAddSuc p)) 169 | \end{code} 170 | 171 | \begin{code} 172 | beqNat0L : forall (n : Nat) -> beqNat 0 n == True -> n == 0 173 | beqNat0L zero refl = refl 174 | beqNat0L (suc n) () 175 | 176 | beqNat0R : forall (n : Nat) -> beqNat n 0 == True -> n == 0 177 | beqNat0R zero refl = refl 178 | beqNat0R (suc n) () 179 | \end{code} 180 | 181 | 182 | \section{Using Tactics on Hypothesis} 183 | 184 | \begin{code} 185 | sucInj : forall (n m : Nat)(b : Bool) -> beqNat (suc n) (suc m) == b -> beqNat n m == b 186 | sucInj n m b p = p 187 | \end{code} 188 | 189 | 190 | \begin{code} 191 | Silly3' : Nat -> Set 192 | Silly3' n = (beqNat n 5 == True -> beqNat (suc (suc n)) 7 == True) -> 193 | True == beqNat n 5 -> True == beqNat (suc (suc n)) 7 194 | 195 | silly3' : forall (n : Nat) -> Silly3' n 196 | silly3' n h p = p 197 | \end{code} 198 | 199 | an exercice 200 | 201 | \begin{code} 202 | plusNSucM : forall (n m : Nat) -> suc (n + m) == n + suc m 203 | plusNSucM = {!!} 204 | 205 | plusInjNN : forall (n m : Nat) -> n + n == m + m -> n == m 206 | plusInjNN zero zero p = refl 207 | plusInjNN zero (suc m) () 208 | plusInjNN (suc n) zero () 209 | plusInjNN (suc n) (suc m) p rewrite (sym (plusNSucM n n)) | (sym (plusNSucM m m)) 210 | = cong suc (plusInjNN n m (eqAddSuc (eqAddSuc p))) 211 | \end{code} 212 | 213 | \section{Varying the Induction Hypothesis} 214 | 215 | \begin{code} 216 | 217 | double : Nat -> Nat 218 | double zero = zero 219 | double (suc n) = suc (suc (double n)) 220 | 221 | doubleInj : forall (n m : Nat) -> double n == double m -> n == m 222 | doubleInj zero zero h = refl 223 | doubleInj zero (suc m) () 224 | doubleInj (suc n) zero () 225 | doubleInj (suc n) (suc m) h = cong suc (doubleInj _ _ (eqAddSuc (eqAddSuc h))) 226 | \end{code} 227 | 228 | exercice 229 | 230 | \begin{code} 231 | beqNatTrue : forall (n m : Nat) -> beqNat n m == True -> n == m 232 | beqNatTrue zero zero h = refl 233 | beqNatTrue zero (suc m) () 234 | beqNatTrue (suc n) zero () 235 | beqNatTrue (suc n) (suc m) h = cong suc (beqNatTrue n m h) 236 | \end{code} 237 | -------------------------------------------------------------------------------- /proof.sty: -------------------------------------------------------------------------------- 1 | % proof.sty (Proof Figure Macros) 2 | % 3 | % version 3.1 (for both LaTeX 2.09 and LaTeX 2e) 4 | % Nov 24, 2005 5 | % Copyright (C) 1990 -- 2005, Makoto Tatsuta (tatsuta@nii.ac.jp) 6 | % 7 | % This program is free software; you can redistribute it or modify 8 | % it under the terms of the GNU General Public License as published by 9 | % the Free Software Foundation; either versions 1, or (at your option) 10 | % any later version. 11 | % 12 | % This program is distributed in the hope that it will be useful 13 | % but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | % GNU General Public License for more details. 16 | % 17 | % Usage: 18 | % In \documentstyle, specify an optional style `proof', say, 19 | % \documentstyle[proof]{article}. 20 | % 21 | % The following macros are available: 22 | % 23 | % In all the following macros, all the arguments such as 24 | % and are processed in math mode. 25 | % 26 | % \infer 27 | % draws an inference. 28 | % 29 | % Use & in to delimit upper formulae. 30 | % consists more than 0 formulae. 31 | % 32 | % \infer returns \hbox{ ... } or \vbox{ ... } and 33 | % sets \@LeftOffset and \@RightOffset globally. 34 | % 35 | % \infer[