├── .github └── workflows │ ├── render.yml │ └── static.yml ├── .gitignore ├── README.md ├── docs ├── index.html ├── slides.pdf └── summary.pdf ├── material ├── w00-intro │ └── 00-intro.md ├── w01-implications_assertions_conditions │ ├── 01-implications_assertions_postconditions.md │ ├── images │ │ └── cfg.png │ ├── w01.pdf │ └── w01.pptx ├── w02-postconditions_preconditions │ ├── 02-preconditions_postconditions_local-consistency.md │ ├── w02.pdf │ └── w02.pptx ├── w03-loop_invariants │ ├── 03-loop_invariants.md │ ├── images │ │ └── program_with_loop.png │ ├── w03.pdf │ └── w03.pptx ├── w04-termination │ ├── 04-termination-proofs.md │ ├── images │ │ └── program_with_assertions.png │ ├── w04.pdf │ └── w04.pptx ├── w05-ocaml │ ├── 05-ocaml.md │ ├── code │ │ ├── hello_world.ml │ │ ├── polynomial_math.ml │ │ ├── student_database.ml │ │ └── whats_the_point.ml │ ├── w05.pdf │ └── w05.pptx ├── w06-list_module │ ├── 06-list-module.md │ ├── w06.pdf │ └── w06.pptx ├── w07-mappings │ ├── 07-mappings.md │ ├── code │ │ ├── key_value_assoc_list.ml │ │ ├── key_value_functional_mapping.ml │ │ └── list_operations.ml │ ├── w07.pdf │ └── w07.pptx ├── w08-tail_recursion │ ├── 08-lazy_lists.md │ ├── code │ │ └── fibonacci_lazy_list.ts │ ├── w08.pdf │ └── w08.pptx ├── w09-side_effects │ ├── 09-side-effects.md │ ├── w09.pdf │ └── w09.pptx ├── w10-modules │ ├── 10-modules.md │ ├── code │ │ ├── Java │ │ │ ├── MapDemo.java │ │ │ └── map │ │ │ │ ├── BinaryTreeMap.java │ │ │ │ ├── IntIntMap.java │ │ │ │ ├── IntOrderedPrintable.java │ │ │ │ ├── IntStringMap.java │ │ │ │ ├── Map.java │ │ │ │ ├── OrderedPrintable.java │ │ │ │ ├── Pair.java │ │ │ │ ├── Printable.java │ │ │ │ └── StringPrintable.java │ │ └── OCaml │ │ │ ├── .gitattributes │ │ │ ├── .gitignore │ │ │ ├── .ocamlformat │ │ │ ├── binarytreemap │ │ │ ├── dune │ │ │ └── libBinaryTreeMap.ml │ │ │ ├── common │ │ │ ├── common.ml │ │ │ └── dune │ │ │ ├── demo.ml │ │ │ ├── dune │ │ │ ├── dune-project │ │ │ ├── intintmap │ │ │ ├── dune │ │ │ └── libIntIntMap.ml │ │ │ ├── intorderedprintable │ │ │ ├── dune │ │ │ └── libIntOrderedPrintable.ml │ │ │ ├── intstringmap │ │ │ ├── dune │ │ │ └── libIntStringMap.ml │ │ │ ├── map │ │ │ ├── dune │ │ │ └── libMap.ml │ │ │ ├── orderedprintable │ │ │ ├── dune │ │ │ └── libOrderedPrintable.ml │ │ │ ├── printable │ │ │ ├── dune │ │ │ └── libPrintable.ml │ │ │ └── stringprintable │ │ │ ├── dune │ │ │ └── libStringPrintable.ml │ ├── w10.pdf │ └── w10.pptx ├── w11-big_step │ ├── 11-big_step.md │ ├── images │ │ ├── image1.png │ │ ├── image2.png │ │ ├── image3.png │ │ ├── image4.png │ │ ├── image5.png │ │ ├── image6.png │ │ ├── image7.png │ │ └── image8.png │ ├── w11.pdf │ └── w11.pptx ├── w12-equational_reasoning │ ├── 12-equational_reasoning.md │ ├── proofs │ │ ├── exam_template.txt │ │ ├── t01.txt │ │ ├── t02.txt │ │ └── t03.txt │ ├── w12.pdf │ └── w12.pptx └── w13-threads │ ├── 13-threads.md │ ├── code │ └── blog_server.ml │ ├── w13.pdf │ └── w13.pptx └── render.sh /.github/workflows/render.yml: -------------------------------------------------------------------------------- 1 | name: Rerender PDFs 2 | 3 | on: 4 | push: 5 | branches: master 6 | pull_request: 7 | branches: master 8 | 9 | workflow_dispatch: 10 | 11 | jobs: 12 | render_summary: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Set up Git repository 17 | uses: actions/checkout@v2 18 | 19 | - run: sudo apt-get update 20 | 21 | - name: install svg to png 22 | run: sudo apt-get install librsvg2-bin 23 | 24 | - name: install texlive 25 | run: sudo apt-get install texlive-lang-german 26 | 27 | - name: install texlive science 28 | run: sudo apt-get install texlive-science 29 | 30 | - name: install pandoc 31 | run: sudo apt-get install pandoc 32 | 33 | - name: create docs folder if not exists 34 | run: mkdir -p docs 35 | 36 | - name: run render.sh 37 | run: | 38 | pandoc -V documentclass=report -V classoption=oneside -V geometry:vmargin=14.5mm -V lang:de --fail-if-warnings --output=docs/summary.pdf material/**/*.md 39 | 40 | - uses: actions/upload-artifact@master 41 | with: 42 | name: summary.pdf 43 | path: docs/summary.pdf 44 | 45 | render_slides: 46 | runs-on: ubuntu-latest 47 | 48 | steps: 49 | - name: Set up Git repository 50 | uses: actions/checkout@v2 51 | 52 | - name: install pdftk 53 | run: sudo apt-get install pdftk 54 | 55 | - name: create docs folder if not exists 56 | run: mkdir -p docs 57 | 58 | - name: merge 59 | run: pdftk material/**/w*.pdf cat output docs/slides.pdf 60 | 61 | - uses: actions/upload-artifact@master 62 | with: 63 | name: slides.pdf 64 | path: docs/slides.pdf 65 | 66 | push_merged_pdfs: 67 | if: github.event_name == 'push' 68 | runs-on: ubuntu-latest 69 | needs: [render_summary, render_slides] 70 | 71 | permissions: 72 | contents: write 73 | 74 | steps: 75 | - uses: actions/checkout@master 76 | 77 | - name: delete old pdfs if exists 78 | run: rm -f docs/*.pdf 79 | 80 | - uses: actions/download-artifact@master 81 | with: 82 | name: slides.pdf 83 | path: docs 84 | 85 | - uses: actions/download-artifact@master 86 | with: 87 | name: summary.pdf 88 | path: docs 89 | 90 | - name: Commit files 91 | run: | 92 | git config --local user.email "github-actions[bot]@users.noreply.github.com" 93 | git config --local user.name "github-actions[bot]" 94 | git add docs/*.pdf -f 95 | git commit -m "Update PDFs" 96 | 97 | - name: Push changes 98 | uses: ad-m/github-push-action@master 99 | with: 100 | github_token: ${{ secrets.GITHUB_TOKEN }} 101 | branch: master 102 | -------------------------------------------------------------------------------- /.github/workflows/static.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Deploy static content to Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | workflow_run: 7 | workflows: ["Rerender PDFs"] 8 | branches: [master] 9 | types: 10 | - completed 11 | 12 | # Allows you to run this workflow manually from the Actions tab 13 | workflow_dispatch: 14 | 15 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 16 | permissions: 17 | contents: read 18 | pages: write 19 | id-token: write 20 | 21 | # Allow one concurrent deployment 22 | concurrency: 23 | group: "pages" 24 | cancel-in-progress: true 25 | 26 | jobs: 27 | # Single deploy job since we're just deploying 28 | deploy: 29 | environment: 30 | name: github-pages 31 | url: ${{ steps.deployment.outputs.page_url }} 32 | runs-on: ubuntu-latest 33 | steps: 34 | - name: Checkout 35 | uses: actions/checkout@v3 36 | - name: Setup Pages 37 | uses: actions/configure-pages@v3 38 | - name: Upload artifact 39 | uses: actions/upload-pages-artifact@v1 40 | with: 41 | # Upload entire repository 42 | path: docs 43 | - name: Deploy to GitHub Pages 44 | id: deployment 45 | uses: actions/deploy-pages@v1 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | docs/*.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FPV Tutorial - SS23 2 | 3 | [![Rerender PDFs](https://github.com/ManuelLerchner/fpv-tutorial-ss23/actions/workflows/render.yml/badge.svg)](https://github.com/ManuelLerchner/subject/actions/workflows/render.yml) 4 | [![Deploy static content to Pages](https://github.com/ManuelLerchner/fpv-tutorial-ss23/actions/workflows/static.yml/badge.svg)](https://github.com/ManuelLerchner/subject/actions/workflows/static.yml) 5 | 6 | ## About 7 | 8 | Materialien für Manuel's FPV-Tutorium im Sommersemester 2023. 9 | 10 | >Die Materialien sind privat erstellt und können Fehler enthalten. Im Zweifelsfall haben immer die **offiziellen** Lehrunterlagen vorrang. 11 | 12 | + Alle Zusammenfassungen dieses Repositories können über [manuellerchner.github.io/fpv-tutorial-SS23/summary.pdf](https://manuellerchner.github.io/fpv-tutorial-SS23/summary.pdf) heruntergeladen werden. 13 | 14 | + Die Tutor-Slides sind unter [manuellerchner.github.io/fpv-tutorial-SS23/slides.pdf](https://manuellerchner.github.io/fpv-tutorial-SS23/slides.pdf) verfügbar. 15 | 16 | ## When do students learn the topics covered in the tutorials? 17 | 18 | By looking at the github-stars as a reference, one can see the `hot` weeks of a semester happen just before an exam. 19 | This is to be expected, however I still found it quite funny. 20 | 21 | [![Star History Chart](https://api.star-history.com/svg?repos=ManuelLerchner/fpv-tutorial-SS23&type=Date)](https://star-history.com/#ManuelLerchner/fpv-tutorial-SS23&Date) 22 | 23 | ## Found an error, or want to add something? 24 | 25 | 1. Fork this Repository 26 | 2. Commit and push your changes to **your** forked repository 27 | 3. Open a Pull Request to this repository 28 | 4. Wait until the changes are merged 29 | 5. A Github Action will automatically render the PDFs and deploy the static content to Github Pages 30 | 31 | ## Contributors 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | FPV-Tutorial-SS23 8 | 9 | 10 | 11 |

FPV-Tutorium-SS23

12 | 13 |

14 | Die Slides für die jeweiligen Wochen, sowie die restlichen Materialien, 15 | können auch einzeln über folgendes Repository heruntergeladen werden: 16 |

17 | 18 |

19 | https://github.com/ManuelLerchner/fpv-tutorial-SS23 22 | - Manuel Lerchner 23 |

24 | 25 |

Inhalt

26 | 27 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/docs/slides.pdf -------------------------------------------------------------------------------- /docs/summary.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/docs/summary.pdf -------------------------------------------------------------------------------- /material/w00-intro/00-intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: FPV-Tutorial - SS23 3 | subtitle: "Materialien für Manuel's FPV-Tutorium im Sommersemester 2023" 4 | author: Manuel Lerchner 5 | toc: true 6 | date: >- 7 | Zuletzt aktualisiert: \today 8 | keywords: 9 | ["FPV", "Tutorium", "Sommersemester", "2023", "TUM"] 10 | urlcolor: blue 11 | header-includes: 12 | - \usepackage{stmaryrd} 13 | include-before: | 14 | # FPV Tutorial - SS23 15 | 16 | ## About 17 | 18 | Materialien für Manuel's FPV-Tutorium im Sommersemester 2023. 19 | 20 | + **Die Materialien sind privat erstellt und können Fehler enthalten. Im Zweifelsfall haben immer die *offiziellen* Lehrunterlagen Vorrang.** 21 | 22 | + Alle Zusammenfassungen dieses Repositories können über [manuellerchner.github.io/fpv-tutorial-SS23/summary.pdf](https://manuellerchner.github.io/fpv-tutorial-SS23/summary.pdf) heruntergeladen werden. 23 | 24 | + Die Tutor-Slides sind unter [manuellerchner.github.io/fpv-tutorial-SS23/slides.pdf](https://manuellerchner.github.io/fpv-tutorial-SS23/slides.pdf) verfügbar. 25 | 26 | ## Found an error, or want to add something? 27 | 28 | 1. Fork this Repository 29 | 2. Commit and push your changes to **your** forked repository 30 | 3. Open a Pull Request to this repository 31 | 4. Wait until the changes are merged 32 | 5. A Github Action will automatically render the PDFs and deploy the static content to Github Pages 33 | 34 | ## Contributors 35 | 36 | [![Contributors](https://contrib.rocks/image?repo=ManuelLerchner/fpv-tutorial-ss23)](https://github.com/ManuelLerchner/fpv-tutorial-ss23/graphs/contributors) 37 | 38 | --- 39 | -------------------------------------------------------------------------------- /material/w01-implications_assertions_conditions/01-implications_assertions_postconditions.md: -------------------------------------------------------------------------------- 1 | # Week 1: Implications, Assertions and Stronges Postconditions 2 | 3 | ## Implications 4 | 5 | Implications are the the key for understanding FPV. They show up in topics such as *Weakest Preconditions*, *Strongest Postconditions*, *Proof by Induction / Structural Induction*... 6 | 7 | ### Definition of Implications 8 | 9 | As you remeber from the "Diskrete Strukturen" course, an implication is a statement of the form $A \implies B$. It is read as: 10 | 11 | + "$A$ implies $B$" 12 | + "If $A$ is true, then $B$ is true" 13 | 14 | It's syntactic sugar for the following statement: 15 | 16 | $$ 17 | A \implies B \iff \neg A \lor B 18 | $$ 19 | 20 | This is a very important statement, because it can be used to simplify complex statements, if you can't remember the specific rules for implications. 21 | 22 | ### Truth Table 23 | 24 | | $A$ | $B$ | $A \implies B$ | 25 | |:---:|:---:|:--------------:| 26 | | F | F | T | 27 | | F | T | T | 28 | | T | F | F | 29 | | T | T | T | 30 | 31 | ### Examples 32 | 33 | Example 1: 34 | 35 | $$ 36 | \begin{aligned} 37 | & x = 1 \implies x \geq 0 \\ 38 | \iff & \neg (x = 1) \lor (x \geq 0) \\ 39 | \iff & (x \neq 1) \lor (x \geq 0) \\ 40 | \iff & true 41 | \end{aligned} 42 | $$ 43 | 44 | Example 2: 45 | 46 | $$ 47 | \begin{aligned} 48 | & A \implies (B \implies A) \\ 49 | \iff & \neg A \lor (B \implies A) \\ 50 | \iff & \neg A \lor (\neg B \lor A) \\ 51 | \iff & \neg A \lor A \lor \neg B \\ 52 | \iff & true \lor \neg B \\ 53 | \iff & true 54 | \end{aligned} 55 | $$ 56 | 57 | ## Assertions 58 | 59 | Assertions are used to **annotate** specific points in a program and to **check** if a given expression is true at that point. If the expression is false, the program will terminate. 60 | 61 | This is usefull if you only want to allow certain values for a variable, because otherwise the program would not work as expected. They can also be used to prove the correctness of a program. Which is the main topic of this course. 62 | 63 | ### Example for MiniJava 64 | 65 | ![Flow Diagram](material/w01-implications_assertions_conditions/images/cfg.png) 66 | 67 | This corresponds to the following program: 68 | 69 | ```java 70 | void main() { 71 | var n = read(); //reads an arbitrary integer 72 | var i = 0; 73 | assert(A); 74 | 75 | var x = 0; 76 | assert(B) 77 | while (i < 10) { 78 | x = x + n; 79 | i = i + 1; 80 | assert(B); 81 | }; 82 | 83 | write(x); 84 | assert(C); 85 | } 86 | ``` 87 | 88 | The challenge is to find strong and precise assertions for the specific points in the program which allow us to prove the correctness of the program. In this case, we want to prove that the program **always** prints $n \cdot 10$ to the console. 89 | This corresponds to Assertion $C \iff x = n \cdot 10$. 90 | 91 | Remember that whenever the programm-flow reaches an assertion, the assertion must be true. Otherwise the program will terminate. 92 | 93 | ### Strength of Assertions 94 | 95 | Two assertions $A$ and $B$ can have different strengths. This happens for example if assertion $A$ is more precise than assertion $B$. 96 | 97 | For example, the assertion $A=5$ is stronger than the assertion $B=5 \lor B=6$, because it is more specific. The assertion $A$ only allows the value $5$, while the assertion $B$ allows the values $5$ and $6$. 98 | 99 | This makes sense intuitively. But in order to use it in practice, we need to define what it means for an assertion to be stronger than another assertion. 100 | 101 | ### Definition of Assertions-Strength 102 | 103 | We say that an assertion $A$ is stronger than an assertion $B$, if $A$ implies $B$. 104 | 105 | Using this definition, we can compare different assertions and determine if they are: 106 | 107 | + **Equivalent**: $A \implies B$ and $B \implies A$ 108 | + **Ordered (eg. A is stronger)**: $A \implies B$ 109 | + **Uncomparable**: $A \not\implies B$ and $B \not\implies A$ 110 | 111 | ### Special Assertions 112 | 113 | Remember that $true$ and $false$ are also valid assertions. They are called **tautologies** and **contradictions** respectively. 114 | 115 | How do they fit into the strength definition? 116 | 117 | + **Tautologies**: $A \implies true$ for all $A$ 118 | + This means that every assertion is stronger than $true$ thereby making $true$ the weakest assertion. 119 | + **Contradictions**: $false \implies A$ for all $A$ 120 | + This means that $false$ is stronger than every assertion thereby making $false$ the strongest assertion. 121 | 122 | In practice those assertions show up in the following cases: 123 | 124 | + **Tautologies**: If you have no information about the variables at a specific time in the program, you can use $true$ as an assertion to express this. 125 | + **Contradictions**: If you have a point that is **never** reached in the program, you can use $false$ as an assertion to express this. The only way for the program to meet all assertions is to never reach such a point. 126 | 127 | ## Strongest Postconditions 128 | 129 | The strongest postcondition of a statement $s$ and a precondition $A$ is the strongest assertion $B$ that holds after the statement $s$ has been executed. 130 | 131 | ### Example 132 | 133 | Consider the following program: 134 | 135 | ```java 136 | void main() { 137 | var i=2; 138 | var x=6; 139 | 140 | assert(x=3*i && i>=0); 141 | 142 | i=i+1; 143 | 144 | //state at this point: 145 | //i = 3 146 | //x = 6 147 | //since the i in the assertions refers to the old value of i, before the statement i=i+1 was executed, the assertion x=3*i is now broken (x=6 != 3*3) 148 | 149 | //can we find a new assertion which explicitly computes the new value of x? 150 | assert(C); 151 | } 152 | ``` 153 | 154 | What is the strongest postcondition of the statement `i=i+1` and the precondition `x==3*i && i>=0`? In other words what is the strongest assertion which we can insert in the second assertion? 155 | 156 | This can be written as: 157 | 158 | $$ 159 | \bf{SP}\llbracket i=i+1 \rrbracket(x=3*i\land i\geq 0) 160 | $$ 161 | 162 | To compute the assertion after the statement `i=i+1` we basically need to **undo** the statement `i=i+1` because the original assertion refered to the old value of $i$, before it was updated. 163 | 164 | > Note: This only works for updates of variables. Other assignments might be alot more complicated. 165 | 166 | We first compute the **undo** of the statement `i=i+1`: 167 | $$ 168 | \bf{Undo} \llbracket i=i+1\rrbracket \equiv i=i-1 169 | $$ 170 | 171 | Then we replace the varibale $i$ (which has already gotten updated) inside the assertion with the **undo-ed** statement: 172 | 173 | $$ 174 | \begin{aligned} 175 | B :=\ & x=3*i\land i\geq 0 \\ 176 | \longrightarrow\ & x=3*(i-1)\land (i-1)\geq 0 \\ 177 | \equiv\ & x=3(i-1)\land i\geq 1\\ 178 | =: &\ C 179 | \end{aligned} 180 | $$ 181 | 182 | In total we have: 183 | 184 | $$ 185 | \begin{aligned} 186 | C:=\ &\bf{SP}\llbracket i=i+1\rrbracket(x=3*i\land i\geq 0)\\ 187 | \equiv& \ x=3*(i-1)\land i\geq 1 188 | \end{aligned} 189 | $$ 190 | -------------------------------------------------------------------------------- /material/w01-implications_assertions_conditions/images/cfg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w01-implications_assertions_conditions/images/cfg.png -------------------------------------------------------------------------------- /material/w01-implications_assertions_conditions/w01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w01-implications_assertions_conditions/w01.pdf -------------------------------------------------------------------------------- /material/w01-implications_assertions_conditions/w01.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w01-implications_assertions_conditions/w01.pptx -------------------------------------------------------------------------------- /material/w02-postconditions_preconditions/02-preconditions_postconditions_local-consistency.md: -------------------------------------------------------------------------------- 1 | # Week 2: Preconditions, Postconditions and Local Consistency 2 | 3 | ## Weakest Preconditions 4 | 5 | Weakest Preconditions are used calculate the minimum requirements, which need to hold bevore an assignment, so that a given Assertion after the assignment holds. 6 | 7 | Its written as: 8 | 9 | $$ 10 | \bf{WP}\llbracket s\rrbracket(e) 11 | $$ 12 | 13 | Where $s$ is a statement and $e$ is an assertion. 14 | 15 | ### Rules 16 | 17 | The rules for calculating the weakest precondition of a MiniJava statement are as follows: 18 | 19 | $$ 20 | \begin{aligned} 21 | \bf{WP}\llbracket {x=read()}\rrbracket(A) &\equiv \forall x. A\\ 22 | \bf{WP}\llbracket write(expr)\rrbracket(A) &\equiv A\\ 23 | \bf{WP}\llbracket x=expr\rrbracket(A) &\equiv A[expr/x]\\ 24 | \bf{WP}\llbracket c \rrbracket(B_{false}, B_{true}) &\equiv (c \land B_{true}) \lor (\neg c \land B_{false})\\ 25 | &\equiv (c \implies B_{true}) \land (\neg c \implies B_{false})\\ 26 | \end{aligned} 27 | $$ 28 | 29 | ### Example 30 | 31 | Consider the following program: 32 | 33 | ```java 34 | void main() { 35 | var r = 5; 36 | assert(A); 37 | var t = 3*r; 38 | assert(t>=0); 39 | } 40 | ``` 41 | 42 | We want to find the minimal requirements which need to hold at `assert(A)` so that `assert(t>=0)` holds after `var t = 3*r;`. 43 | 44 | We can calculate this using the following formula: 45 | 46 | $$ 47 | \begin{aligned} 48 | & \bf{WP}\llbracket t = 3*r\rrbracket(t \geq 0) \\ 49 | \equiv\ & 3*r \geq 0 \\ 50 | \equiv\ & r \geq 0\ =: A 51 | \end{aligned} 52 | $$ 53 | 54 | Now we know, that for the assertion `t>=0` to hold after `var t = 3*r;`, the assertion `r>=0` needs to hold before `var t = 3*r;`. 55 | 56 | ## Local Consistency 57 | 58 | Two assertions $A$ and $B$ are locally consistent, if $A$ is **stronger** than the **weakest precondition** of $B$. This is written as: 59 | 60 | $$ 61 | A \implies \bf{WP}\llbracket s\rrbracket(B) 62 | $$ 63 | 64 | >Note that it is not required that $A= \bf{WP}\llbracket s\rrbracket(B)$. Because a stronger assertion than required is also fine. 65 | 66 | Local consistency is important: It mathematically proves that whenever the assertion $A$ holds, then the assertion $B$ holds after the statement $s$. This can be used to prove that a program actually computes what it is supposed to compute. 67 | 68 | ### Example Local Consistency 69 | 70 | Consider the following program: 71 | 72 | ```java 73 | void main() { 74 | var x = 30; 75 | assert(x>25); //A 76 | x=x+5; 77 | assert(x!=0); //B 78 | } 79 | ``` 80 | 81 | $$ 82 | \begin{aligned} 83 | &A \equiv x>25 \\ 84 | &B \equiv x \neq 0 \\ 85 | &s \equiv x=x+5\\ 86 | \end{aligned} 87 | $$ 88 | 89 | At the moment all the Assertions are arbitrary, and there is no garantee that they actually hold during the execution of the program. 90 | 91 | To prove them, we need to: 92 | 93 | 1. Show that all the assertions are locally consistent 94 | 2. We arrive at $true$ at the start of the program 95 | 96 | #### Local Consistency of $A$ and $B$ 97 | 98 | We can calculate the weakest precondition of $B$ and $s$ as follows: 99 | 100 | $$ 101 | \begin{aligned} 102 | &\bf{WP}\llbracket s\rrbracket(B) \\ 103 | \equiv\ &\bf{WP}\llbracket x=x+5\rrbracket(x \neq 0) \\ 104 | \equiv\ & x+5 \neq 0 \\ 105 | \equiv\ & x \neq -5 \ =: B'\\ 106 | \end{aligned} 107 | $$ 108 | 109 | We can check the local consistency of $A$ and $B$ by checking if $A \implies B'$ holds. 110 | 111 | This is the case, because: 112 | 113 | $$ 114 | \begin{aligned} 115 | & A \implies B' \\ 116 | \equiv\ & x>25 \implies x \neq -5\\ 117 | \equiv\ & true\\ 118 | \end{aligned} 119 | $$ 120 | 121 | So we proved that $A$ and $B$ are locally consistent. This means that whenever $A$ holds, then $B$ holds after the statement $s$. 122 | 123 | #### Weakest Precondition of $A$ 124 | 125 | If we compute the weakest precondition of $A$ and `x=30;` we get: 126 | 127 | $$ 128 | \begin{aligned} 129 | &\bf{WP}\llbracket x=30\rrbracket(x>25) \\ 130 | \equiv\ & 30>25 \\ 131 | \equiv\ & true =: A'\\ 132 | \end{aligned} 133 | $$ 134 | 135 | This is obviously also locally consistent, because $true \implies A' \equiv true \implies true \equiv true$. 136 | 137 | Since we arrived at $true$, we know that the whole chain of assertions from the start to the end of the program holds and is locally consistent. 138 | 139 | This means that we proved that when the assertion at the start (aka. $true$) holds,then the assertion $A$ and consequently Assertion $B$ holds. 140 | 141 | In this case, we proved that in all instances of the program, the variable $x$ cannot be $0$ at the end. 142 | -------------------------------------------------------------------------------- /material/w02-postconditions_preconditions/w02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w02-postconditions_preconditions/w02.pdf -------------------------------------------------------------------------------- /material/w02-postconditions_preconditions/w02.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w02-postconditions_preconditions/w02.pptx -------------------------------------------------------------------------------- /material/w03-loop_invariants/03-loop_invariants.md: -------------------------------------------------------------------------------- 1 | # Week 3: Loop Invariants 2 | 3 | ## What is a loop invariant? 4 | 5 | A loop invariant is an assertion that holds in each iteration of a loop. Finding such a loop invariant is needed to calculate weakest preconditions for programs with loops, because the **normal** way of finding the preconditions does not work for loops. 6 | 7 | ## The Problem with Loops 8 | 9 | Lets say you are trying to calculate the weakest precondition for the following program: 10 | 11 | ![Program with loop](material/w03-loop_invariants/images/program_with_loop.png) 12 | 13 | The normal way of finding the weakest precondition would be to start at the end of the program and work your way backwards. 14 | 15 | $$ 16 | \begin{aligned} 17 | I& \equiv \bf{WP}\llbracket i j){ 15 | i += 2; 16 | j += 1; 17 | } 18 | console.log("Finished"); 19 | ``` 20 | 21 | On the other hand, the following program will always halt: 22 | 23 | ```typescript 24 | let i = 17; 25 | let j = 5; 26 | while (i > j){ 27 | i += 1; 28 | j += 2; 29 | } 30 | console.log("Finished"); 31 | ``` 32 | 33 | But how can we be sure that a program will always halt? In some cases it is not so obvious as in the examples above. 34 | 35 | This is where **termination proofs** come in. 36 | 37 | ## What is a Termination Proof? 38 | 39 | In a termination proof, you generally try to prove that a certain variable only takes on positive values inside a loop. Furthermore, you try to prove that the variable is decreased by at least one in each iteration of the loop. 40 | 41 | This means that the variable will eventually reach zero (or less) and the cannot be entered again. Because this would violate the Assertion we defined. 42 | 43 | But just coming up with arbitrary assertions and then claiming that they prove termination is not enough. We also need to show that those assertions are **localy consistent**. 44 | 45 | ## How to do a Termination Proof? 46 | 47 | Bevore we can perform a termination proof, it is necessary to understand what the loop actually does. 48 | 49 | In the second example above our intuition tells us that the loop will eventually terminate. Because the variable `j` is increased by two in each iteration, while `i` is only increased by one. This means that `j` will eventually overtake `i` and the loop will terminate. 50 | 51 | With this understanding we can define an auxiliary variable `r` which represents this intuition. 52 | 53 | Since we only want to prove that the loop terminates, we just need to prove $true$ at the end of the program. 54 | 55 | In general, we need to insert the following assertions / statements 56 | 57 | ![Flowchart with auxiliary variable](./material/w04-termination/images/program_with_assertions.png) 58 | 59 | Notice that we need both these assertions to prove termination: 60 | 61 | + $r > 0$ at the beginning of the loop 62 | + $r > r_e$ at the end of the loop, right bevore $r = r_e$ 63 | 64 | Now the task is to show the following, we have proven that the loop terminates: 65 | 66 | + local consistency of all assertions 67 | + arrived at $true$ at the start of the program 68 | + The special assertions $r \geq 0$ and $r > r_e$ are also localy consistent 69 | -------------------------------------------------------------------------------- /material/w04-termination/images/program_with_assertions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w04-termination/images/program_with_assertions.png -------------------------------------------------------------------------------- /material/w04-termination/w04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w04-termination/w04.pdf -------------------------------------------------------------------------------- /material/w04-termination/w04.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w04-termination/w04.pptx -------------------------------------------------------------------------------- /material/w05-ocaml/05-ocaml.md: -------------------------------------------------------------------------------- 1 | # Week 5: OCaml 2 | 3 | ## Basic Syntax 4 | 5 | ### Comments 6 | 7 | ```ocaml 8 | (* This is a comment *) 9 | ``` 10 | 11 | ### Variables 12 | 13 | ```ocaml 14 | let x = 1;; 15 | ``` 16 | 17 | ### Functions 18 | 19 | ```ocaml 20 | let f x = x + 1;; 21 | let succ: int -> int = fun x -> x + 1;; 22 | ``` 23 | 24 | ### Tuples 25 | 26 | ```ocaml 27 | let x = (1, true);; 28 | ``` 29 | 30 | ### Lists 31 | 32 | ```ocaml 33 | let x = [1; 2; 3];; 34 | let y = 1 :: 2 :: 3 :: [];; 35 | ``` 36 | 37 | ### Records 38 | 39 | ```ocaml 40 | type person = { name: string; age: int };; 41 | let x = { name = "John"; age = 42 };; 42 | let name = x.name;; 43 | ``` 44 | 45 | ### If-then-else 46 | 47 | ```ocaml 48 | let x = if 3 < 6 then "1" else "2";; 49 | ``` 50 | 51 | ### Pattern Matching 52 | 53 | ```ocaml 54 | let x = match 3 with 55 | | 1 -> "1" 56 | | 2 -> "2" 57 | | _ -> "else";; 58 | 59 | let y = match "up" with 60 | | "up" -> (0, 1) 61 | | "down" -> (0, -1) 62 | | "left" -> (-1, 0) 63 | | "right" -> (1, 0) 64 | ``` 65 | 66 | ## Example Programs 67 | 68 | ### Advanced Hello World 69 | 70 | ```ocaml 71 | 72 | let welcome_string = "lmaCO ot emocleW ,!dlroW olleH" 73 | 74 | let rec char_iterator sentence = 75 | if sentence = "" then () 76 | else 77 | let head = String.get sentence 0 in 78 | let tail = String.sub sentence 1 (String.length sentence - 1) in 79 | char_iterator tail; 80 | print_char head 81 | 82 | (* Call Function: Result will be visible in the console when loaded via utop *) 83 | let _ = char_iterator welcome_string 84 | ``` 85 | 86 | ## Debuging OCaml 87 | 88 | ### Using the `#use` command in `utop` 89 | 90 | This method works best for single files containing the code you want to debug. 91 | The `#use` command works by just copy-pasting the entire 92 | content of the file into the `utop`-environment. It also shadows previous definitions of variables and functions. 93 | 94 | 1. Enter into the `root`-directory of the project and run `dune build` to initially build the project. 95 | 96 | ```ocaml 97 | dune build 98 | ``` 99 | 100 | 2. Open `utop` via `dune utop src` 101 | 102 | ```ocaml 103 | dune utop src 104 | ``` 105 | 106 | In all projects you will encounter, dune is configured in a way that will allow this command to work. 107 | 108 | This will open `utop` with the project's `src`-directory as the current working directory. 109 | 110 | 3. Reload the files 111 | 112 | + Instead of closing and reopening `utop` every time you change something in the files, you can use the `#use` command to load the files again. 113 | 114 | + But you need to be careful, because older definitions may still be around after reloading the file. 115 | 116 | ```ocaml 117 | #use "src/main.ml";; 118 | ``` 119 | -------------------------------------------------------------------------------- /material/w05-ocaml/code/hello_world.ml: -------------------------------------------------------------------------------- 1 | let welcome_string = "lmaCO ot emocleW ,!dlroW olleH" 2 | 3 | let rec char_iterator sentence = 4 | if sentence = "" then () 5 | else 6 | let head = String.get sentence 0 in 7 | let tail = String.sub sentence 1 (String.length sentence - 1) in 8 | char_iterator tail; 9 | print_char head 10 | 11 | (* Call Function: Result will be visible in the console when loaded via utop *) 12 | let _ = char_iterator welcome_string 13 | -------------------------------------------------------------------------------- /material/w05-ocaml/code/polynomial_math.ml: -------------------------------------------------------------------------------- 1 | 2 | (* A polynomial is represented by its coefficients *) 3 | (* Example: 2x^3 - 3x + 1 is represented by [2.0; 0.0; -3.0; 1.0] *) 4 | type polynomial = float list;; 5 | 6 | (* 2x^3 - 3x + 1 *) 7 | let my_poly:polynomial = [2.0; 0.0; -3.0; 1.0] 8 | 9 | 10 | (* evaluates a polynomial at a given point *) 11 | let evaluate (p:polynomial) (x:float) : float = 12 | let y = List.fold_left (fun acc c -> acc *. x +. c) 0.0 p in 13 | y 14 | 15 | (* calculates the derivative of a polynomial *) 16 | let derivative (p:polynomial) : polynomial = 17 | let rec derivative_helper (p:polynomial) (n:int) : polynomial = 18 | match p with 19 | | [] -> [] 20 | | x::[] -> [] 21 | | h::t -> (float_of_int n) *. h :: derivative_helper t (n-1) 22 | in 23 | derivative_helper p (List.length p - 1) 24 | 25 | (* Do some fun stuff *) 26 | 27 | (* Recursively iterates the newton method until the difference between the 28 | * current and previous x is less than epsilon *) 29 | let newton (p:polynomial) (x0:float) (epsilon:float) : float = 30 | let derivative_p = derivative p in 31 | let rec newton_helper (p:polynomial) (x0:float) (epsilon:float) : float = 32 | let x1 = x0 -. (evaluate p x0) /. (evaluate derivative_p x0) in 33 | if abs_float (x1 -. x0) < epsilon then x1 34 | else newton_helper p x1 epsilon 35 | in 36 | newton_helper p x0 epsilon 37 | 38 | -------------------------------------------------------------------------------- /material/w05-ocaml/code/student_database.ml: -------------------------------------------------------------------------------- 1 | type grade = int * float 2 | 3 | type student = { 4 | first_name : string; 5 | last_name : string; 6 | id : int; 7 | semester : int; 8 | grades : grade list; 9 | } 10 | 11 | let (manuel : student) = 12 | { 13 | first_name = "Manuel"; 14 | last_name = "Lerchner"; 15 | id = 2; 16 | semester = 4; 17 | grades = []; 18 | } 19 | 20 | let (david : student) = 21 | { 22 | first_name = "David"; 23 | last_name = "Test"; 24 | id = 2; 25 | semester = 2; 26 | grades = []; 27 | } 28 | 29 | type database = student list 30 | 31 | let (db : database) = [ manuel; david ] 32 | let insert (s : student) (db : database) = s :: db 33 | 34 | let rec find_by_id (id : int) (db : database) = 35 | match db with 36 | | [] -> [] 37 | | stud :: xs -> if stud.id = id then [ stud ] else find_by_id id xs 38 | 39 | let find_by_last_name (name : string) (db : database) = 40 | List.find_all (fun stud -> stud.last_name = name) db 41 | 42 | let rec find_by_last_name_2 (name : string) (db : database) = 43 | match db with 44 | | [] -> [] 45 | | stud :: xs -> 46 | let remaining_students = find_by_last_name_2 name xs in 47 | if stud.last_name = name then stud :: remaining_students 48 | else remaining_students 49 | -------------------------------------------------------------------------------- /material/w05-ocaml/code/whats_the_point.ml: -------------------------------------------------------------------------------- 1 | type vector3 = float * float * float 2 | 3 | let (p1 : vector3) = (1.0, -2.0, 3.0) 4 | let (p2 : vector3) = (1.0, 3.0, 6.0) 5 | let p3 = (1.0, 8.0, -3.0) 6 | 7 | let string_of_vector3 (v : vector3) = 8 | let x, y, z = v in 9 | "(" ^ string_of_float x ^ "," ^ string_of_float y ^ "," ^ string_of_float z 10 | ^ ")" 11 | 12 | let vector3_add (a : vector3) (b : vector3) = 13 | let x1, y1, z1 = a in 14 | let x2, y2, z2 = b in 15 | (x1 +. x2, y1 +. y2, z1 +. z2) 16 | 17 | let length (v : vector3) = 18 | let x, y, z = v in 19 | sqrt ((x *. x) +. (y *. y) +. (z *. z)) 20 | 21 | let vector3_max (a : vector3) (b : vector3) = 22 | let a_longer_b = length a > length b in 23 | if a_longer_b then a else b 24 | 25 | let combine a b c = 26 | let max = vector3_max b c in 27 | string_of_vector3 (vector3_add a max) 28 | -------------------------------------------------------------------------------- /material/w05-ocaml/w05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w05-ocaml/w05.pdf -------------------------------------------------------------------------------- /material/w05-ocaml/w05.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w05-ocaml/w05.pptx -------------------------------------------------------------------------------- /material/w06-list_module/06-list-module.md: -------------------------------------------------------------------------------- 1 | # Week 6: List Module 2 | 3 | ## Lists in OCaml 4 | 5 | Lists in ocaml are basically linked lists. They are defined as follows: 6 | 7 | ```ocaml 8 | let my_list = [1; 2; 3; 4; 5] 9 | ``` 10 | 11 | Since they are linked lists, you don't have direct access to the elements in the list. You can only access the head and the tail of the list. The head is the first element in the list and the tail is the rest of the list. The head is an element and the tail is a list. The tail can be an empty list. 12 | 13 | ```ocaml 14 | let my_list = [1; 2; 3; 4; 5] 15 | 16 | let head = List.hd my_list (* head = 1 *) 17 | let tail = List.tl my_list (* tail = [2; 3; 4; 5] *) 18 | ``` 19 | 20 | Since Linked lists are recursive in nature, most of the functions that operate on lists are recursive. For example, the length function is defined as follows: 21 | 22 | ### Example Length 23 | 24 | ```ocaml 25 | let rec length l = 26 | match l with 27 | | [] -> 0 28 | | _ :: xs -> 1 + length xs 29 | ``` 30 | 31 | + This basically means that the length of list $l=\underbrace{[a_1, a_2, \ldots, a_n]}_{\text{list}}$ can be recursively defined as 32 | + $\text{length}(\underbrace{[a_1, a_2, \ldots, a_n]}_{\text{l}})=1 + \text{length}(\underbrace{[a_2, \ldots, a_n]}_{\text{tail l}})$. 33 | 34 | + Since we need a base case for the recursion, we define the length of an empty list to be 0. 35 | + $\text{length}([]) = 0$. 36 | 37 | Many other functions on lists are defined recursively. For example, the reverse function is defined as follows: 38 | 39 | ## Binary Search Tree 40 | 41 | ### Binary Search Tree in OCaml 42 | 43 | A binary search tree is a binary tree where the value of the left child is less than the value of the parent and the value of the right child is greater than the value of the parent. The following is an example of a binary search tree: 44 | 45 | ```ocaml 46 | type tree = 47 | | Empty 48 | | Node of int * tree * tree 49 | 50 | let my_tree = 51 | Node(6, 52 | Node(3, 53 | Node(1, Empty, Empty), 54 | Node(4, Empty, Empty) 55 | ), 56 | Node(8, 57 | Node(7, Empty, Empty), 58 | Node(9, Empty, Empty) 59 | ) 60 | ) 61 | ``` 62 | 63 | The Tree type is defined as follows: 64 | 65 | ```ocaml 66 | type tree = 67 | | Empty 68 | | Node of int * tree * tree 69 | ``` 70 | 71 | This means that a tree is either an empty node or a node with a left subtree, a value and a right subtree. The left and right subtrees are also trees. The value is an integer. 72 | 73 | The syntax `Node of int * tree * tree` means that the constructor `Node` takes three arguments. The first argument is an integer and the second and third arguments are trees. The result of the constructor is a value of type tree. 74 | 75 | Since Binary Search trees are again recursive in nature, most of the functions that operate on them are recursive. For example, the function `insert` is defined as follows: 76 | 77 | #### Example Insert 78 | 79 | ```ocaml 80 | let rec insert v t = 81 | match t with 82 | | Empty -> Node(v, Empty, Empty) 83 | | Node(y, l, r) -> 84 | if v < y then 85 | Node(y, insert v l, r) 86 | else if v > y then 87 | Node(y, l, insert v r) 88 | else 89 | t 90 | ``` 91 | 92 | It takes a value `v` and a tree `t` and returns a new tree with the value `v` inserted into the tree `t`. If the value `v` is already present in the tree `t`, then the same tree `t` is returned. 93 | 94 | It works as follows: 95 | 96 | + If the tree is empty, then the value `v` is inserted into the tree as the root node. 97 | 98 | + If the tree is not empty: 99 | + If the value `v` is less than the value of the root node, then the value `v` is inserted into the left subtree. 100 | + If the value `v` is greater than the value of the root node, then the value `v` is inserted into the right subtree. 101 | + Else nothing is done and the same tree is returned. 102 | 103 | As you can see from this example, it is not possible to change the value of a node in a tree. This is because the tree is *immutable*. 104 | 105 | If you want to change the value of a node, you have to create a new tree with the new value. 106 | 107 | This means, that if we need to insert a value in the right subtree of a node, we have to create a completely new tree with the new value inserted, and then replace the right subtree of the node with the new tree. 108 | 109 | At first this seams unnecessary and inefficient, but in practise it is not that big of a deal. This is because the compilers of functional programs are in general very good at optimizing the code, since they can make more assumptions about the code due to the functional nature of the language. This means that the compiler can do a lot of optimizations that are not possible in imperative languages. 110 | -------------------------------------------------------------------------------- /material/w06-list_module/w06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w06-list_module/w06.pdf -------------------------------------------------------------------------------- /material/w06-list_module/w06.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w06-list_module/w06.pptx -------------------------------------------------------------------------------- /material/w07-mappings/07-mappings.md: -------------------------------------------------------------------------------- 1 | # Week 7: Advanced List Operations 2 | 3 | ## List Reduce 4 | 5 | The `List` module contains a number of useful functions for working with lists. You can find the documentation for the `List` module [here](https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html). 6 | 7 | Lets look at the `List.reduce` functions: 8 | 9 | ### `List.fold_left` 10 | 11 | Fold left is a function that takes a reducer function, an initial value, and a list. It then applies the reducer function to each element of the list, starting with the initial value, and 12 | then *eating* itself through the list from left to right. 13 | 14 | It works just like the `Stream.reduce` function in Java 15 | 16 | ```ocaml 17 | # List.fold_left (fun acc x -> acc + x) 0 [7; 8; -9; 10];; 18 | - : int = 16 19 | ``` 20 | 21 | If we split up the steps we get something like this: 22 | 23 | | list | | 7 | 8 | -9 | 10 | 24 | | --- | --- | --- | --- | --- | --- | 25 | | fold_left | acc | l[0] | l[1] | l[2] | l[3] | 26 | | | **0** | 7 | 8 | -9 | 10 | 27 | | | | 7 | 8 | -9 | 10 | 28 | | | | | 15 | -9 | 10 | 29 | | | | | | 6 | 10 | 30 | | | | | | | **16** | 31 | 32 | In each step we combine the accumulator with the next element in the list, and then use that as the accumulator for the next step. 33 | 34 | It is called `fold_left` because it implicitly groups the elements of the list from left to right. 35 | 36 | $$ 37 | \begin{aligned} 38 | list&=[7, 8, -9, 10]\\ 39 | fold\_left(f, 0, list) &= f(f(f(f(0, 7), 8), -9), 10) 40 | \end{aligned} 41 | $$ 42 | 43 | ### `List.fold_right` 44 | 45 | `List.fold_right` is similar to `List.fold_left` except that it groups the elements of the list from right to left. 46 | 47 | It has a different type signature than `List.fold_left`: 48 | 49 | ```ocaml 50 | # List.fold_right (fun x acc -> acc + x) [7; 8; -9; 10] 0;; 51 | - : int = 16 52 | ``` 53 | 54 | | list | 7 | 8 | -9 | 10 | | 55 | | --- | --- | --- | --- | --- | --- | 56 | | fold_right | l[0] | l[1] | l[2] | l[3] | acc | 57 | | | 7 | 8 | -9 | 10 | **0** | 58 | | | 7 | 8 | -9 | 10 | | 59 | | | 7 | 8 | 1 | | | 60 | | | 7 | 9 | | | | 61 | | | **16** | | | | | 62 | 63 | $$ 64 | \begin{aligned} 65 | list&=[7, 8, -9, 10]\\ 66 | fold\_right(f, list, 0) &= f(7, f(8, f(-9, f(10, 0)))) 67 | \end{aligned} 68 | $$ 69 | -------------------------------------------------------------------------------- /material/w07-mappings/code/key_value_assoc_list.ml: -------------------------------------------------------------------------------- 1 | type ('k, 'v) database = ('k * 'v) list 2 | 3 | (* Define a an empty databse*) 4 | let (my_database : (int, string) database) = [] 5 | 6 | (* Methods *) 7 | let is_empty (db : ('k * 'v) list) = match db with [] -> true | _ -> false 8 | 9 | let get (key : 'k) (db : ('k * 'v) list) = 10 | let entry = List.find_opt (fun (k, _) -> key = k) db in 11 | Option.map (fun (_, v) -> v) entry 12 | 13 | let contains_key (key : 'k) (db : ('k * 'v) list) = get key db <> None 14 | 15 | let remove (key : 'k) (db : ('k * 'v) list) = 16 | List.filter (fun (k, _) -> k <> key) db 17 | 18 | let put (key : 'k) (value : 'v) (db : ('k * 'v) list) = 19 | let cleared_list = remove key db in 20 | (key, value) :: cleared_list 21 | 22 | let keys (db : ('k * 'v) list) = List.map fst db 23 | let values (db : ('k * 'v) list) = List.map snd db 24 | 25 | (* Example *) 26 | let my_database = put 1 "Hallo" my_database 27 | (* we now inserted (1,"Hallo") *) 28 | 29 | (* so we can query this parameter now *) 30 | let value = get 1 my_database 31 | 32 | (* we can remove it again *) 33 | let my_database = remove 1 my_database 34 | 35 | (* the list is now empty *) 36 | let is_empty = is_empty my_database 37 | -------------------------------------------------------------------------------- /material/w07-mappings/code/key_value_functional_mapping.ml: -------------------------------------------------------------------------------- 1 | type ('k, 'v) database = 'k -> 'v option 2 | 3 | (* Define a Databse, with x²+1 as base case *) 4 | let (my_database : (int, int) database) = fun x -> Some ((x * x) + 1) 5 | 6 | (* Methods *) 7 | let is_empty _ = failwith "impossible" 8 | let get (key : 'k) (db : 'k -> 'v option) = db key 9 | 10 | let put (key : 'k) (value : 'v) (db : 'k -> 'v option) x = 11 | if x = key then Some value else db key 12 | 13 | let contains_key (key : 'k) (db : 'k -> 'v option) = get key db <> None 14 | 15 | let remove (key : 'k) (db : 'k -> 'v option) x = 16 | if x = key then None else db key 17 | 18 | let keys _ = failwith "inpossible" 19 | let values _ = failwith "inpossible" 20 | 21 | (* Example *) 22 | 23 | (* the databse will return Some (x*x)+1 for all queries at this point *) 24 | let get_some_value = get 3 my_database 25 | (* will return Some 10 *) 26 | 27 | let my_database = put 0 (-1) my_database 28 | (* updates the databse to answer *) 29 | (* if we query 0 we now get -1 as the answer *) 30 | 31 | let my_database = remove 8 my_database 32 | (* deletes the entry for 8 *) 33 | (* now querying 8 will return in None *) 34 | -------------------------------------------------------------------------------- /material/w07-mappings/code/list_operations.ml: -------------------------------------------------------------------------------- 1 | let squaresum (xs : int list) = List.fold_left (fun acc x -> acc + (x * x)) 0 xs 2 | 3 | let float_list (xs : int list) = List.map float_of_int xs 4 | 5 | let to_string xs = 6 | let list_part = 7 | List.fold_left (fun acc v -> acc ^ string_of_int v ^ ";") "" xs 8 | in 9 | "[" ^ list_part ^ "]" 10 | 11 | let part_even xs = 12 | let even, uneven = List.partition (fun x -> x mod 2 = 0) xs in 13 | even @ uneven 14 | -------------------------------------------------------------------------------- /material/w07-mappings/w07.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w07-mappings/w07.pdf -------------------------------------------------------------------------------- /material/w07-mappings/w07.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w07-mappings/w07.pptx -------------------------------------------------------------------------------- /material/w08-tail_recursion/08-lazy_lists.md: -------------------------------------------------------------------------------- 1 | # Week 8: Lazy Lists 2 | 3 | A lazy list is a list that is not fully evaluated until it is needed. This is 4 | useful for representing infinite lists, or lists that are too large to fit in 5 | memory. 6 | 7 | Examples of infinite lists include the list of all natural numbers, the list of 8 | all prime numbers, and the list of all Fibonacci numbers. 9 | 10 | ## Lazy lists in OCaml 11 | 12 | One way to implement lazy lists in OCaml is to use the `Lazy` module. But we are going to define our own lazy list type, which we will call `'a llist`. 13 | 14 | ```ocaml 15 | type 'a llist = Cons of 'a * (unit -> 'a llist) 16 | ``` 17 | 18 | This type definition is a bit tricky. It says that a lazy list consists of a value of type `'a` and a function that returns another lazy list. The function is called a _thunk_. It is a function that takes no arguments and returns a lazy list. The thunk is used to delay the evaluation of the tail of the list. 19 | 20 | Here is an example of a lazy list of natural numbers: 21 | 22 | ```ocaml 23 | let rec from n = Cons (n, fun () -> from (n + 1)) 24 | ``` 25 | 26 | It basically says that the lazy list `from n` consists of the value `n` and a thunk that returns the lazy list `from (n + 1)`. 27 | 28 | Here is an example of a lazy list of Fibonacci numbers: 29 | 30 | ```ocaml 31 | let rec fib_step a b = Cons (a, fun () -> fib_step b (a + b)) 32 | ``` 33 | 34 | The parameters `a` and `b` are the two previous Fibonacci numbers. The lazy list `fib_step a b` consists of the value `a` and a thunk that returns the lazy list `fib_step b (a + b)`. Of course, the first two Fibonacci numbers are 0 and 1, so we can define the lazy list of all Fibonacci numbers as follows: 35 | 36 | ```ocaml 37 | let fib = fib_step 0 1 38 | ``` 39 | 40 | This list is infinite, but since its generation is lazy, we can still make use of it. 41 | 42 | ## Partial Application 43 | 44 | Functions in OCaml are curried by default. This means that a function that takes two arguments is actually a function that takes one argument and returns a function that takes another argument. For example, the function `(+)` is defined as follows: 45 | 46 | ```ocaml 47 | let (+) x y = x + y 48 | ``` 49 | 50 | This is equivalent to the following definition: 51 | 52 | ```ocaml 53 | let (+) = fun x -> fun y -> x + y 54 | ``` 55 | 56 | The function `(+)` takes one argument `x` and returns a function that takes another argument `y` and returns the sum of `x` and `y`. 57 | 58 | We can partially apply a function by passing it only some of its arguments. For example, we can define a function `inc` that adds 1 to its argument as follows: 59 | 60 | ```ocaml 61 | let inc = (+) 1 62 | 63 | let x = inc 5 64 | # val x : int = 6 65 | ``` 66 | 67 | The List module defines a function `map` that takes a function `f` and a list `xs` and returns a list of the results of applying `f` to the elements of `xs`. We can partially apply `map` to define a function `double` that doubles all the elements of a list: 68 | 69 | ```ocaml 70 | let double = List.map (( * ) 2) 71 | 72 | let xs = double [1; 2; 3] 73 | # val xs : int list = [2; 4; 6] 74 | ``` 75 | 76 | Also the `inc` function defined above can be used with `map`: 77 | 78 | ```ocaml 79 | let xs = List.map inc [1; 2; 3] 80 | # val xs : int list = [2; 3; 4] 81 | ``` 82 | 83 | Which is equivalent to: 84 | 85 | ```ocaml 86 | let xs = List.map ((+) 1) [1; 2; 3] 87 | # val xs : int list = [2; 3; 4] 88 | ``` 89 | -------------------------------------------------------------------------------- /material/w08-tail_recursion/code/fibonacci_lazy_list.ts: -------------------------------------------------------------------------------- 1 | type llist = [T, () => llist]; 2 | 3 | function fibonaccci_generator(): llist { 4 | function fib_step(a: number, b: number): llist { 5 | return [a, () => fib_step(b, a + b)]; 6 | } 7 | return fib_step(0, 1); 8 | } 9 | 10 | let fibs = fibonaccci_generator(); 11 | 12 | for (let i = 0; i < 10; i++) { 13 | let [val, next_generator] = fibs; 14 | 15 | console.log(val); 16 | fibs = next_generator(); 17 | } 18 | 19 | // Output: 20 | // 0 21 | // 1 22 | // 1 23 | // 2 24 | // 3 25 | // 5 26 | // 8 27 | // 13 28 | // 21 29 | // 34 30 | 31 | // The generator works as follows: 32 | // [0 1] 33 | // 0 [1 1] 34 | // 0 1 [1 2] 35 | // 0 1 1 [2 3] 36 | // 0 1 1 2 [ ... ] 37 | -------------------------------------------------------------------------------- /material/w08-tail_recursion/w08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w08-tail_recursion/w08.pdf -------------------------------------------------------------------------------- /material/w08-tail_recursion/w08.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w08-tail_recursion/w08.pptx -------------------------------------------------------------------------------- /material/w09-side_effects/09-side-effects.md: -------------------------------------------------------------------------------- 1 | # Week 9: Side Effects, Units and Exceptions 2 | 3 | ## Side Effects 4 | 5 | In functional programming, side effects are a way of interacting with the outside world. For example, printing to the screen, reading from a file, or reading from the keyboard are all side effects. They are called side effects because they happen outside of the control of the program. In other words, the program cannot control when the user types something on the keyboard, or when the user clicks the mouse, or when data arrives from the network. 6 | 7 | This also means that repeated calls to a function with side effects may produce different results. For example, if a function reads from the keyboard, then each time it is called, it may read a different value. This is in contrast to a function that does not have side effects, which will always return the same value when called with the same arguments. Those so called `pure` functions are the ones we have been writing so far. 8 | 9 | Side effects are not necessarily bad. In fact, they are necessary for a program to be useful. However, they do make it harder to reason about the program. For example, if a function has side effects, then it is not enough to look at the function to understand what it does. You also need to know what side effects it has. This is in contrast to a pure function, which you can understand just by looking at the function itself. 10 | 11 | ### Example File IO 12 | 13 | Let's look at an example of a function with side effects. The following function reads the first line of a file and returns it as a string. 14 | 15 | ```ocaml 16 | let read_file (filename : string) : string = 17 | let ic = open_in filename in 18 | let row = input_line ic in 19 | close_in ic; 20 | row 21 | ``` 22 | 23 | This function has side effects because it reads from a file. It is not a pure function because it does not always return the same value when called with the same arguments. 24 | 25 | Writing to a file works similarly. The following function writes a string to a file. 26 | 27 | ```ocaml 28 | let write_file (filename : string) (row : string) : unit = 29 | let oc = open_out filename in 30 | output_string oc row; 31 | close_out oc 32 | ``` 33 | 34 | ## Exceptions 35 | 36 | Exceptions are a way of handling errors. They are called exceptions because they are exceptional. They may occur in the normal course of a program, but they are not expected to occur. For example, if a function reads from a file, then it may fail if the file does not exist. This is an exceptional case because the file is expected to exist. 37 | 38 | But sometimes we want exceptions to occur. For example if we read to the end of a file, then we want to know that we have reached the end of the file. Ocaml has a special exception for this case called `End_of_file`. We can use this exception to detect when we have reached the end of a file. 39 | 40 | ```ocaml 41 | let rec read_file (filename : string) : string list = 42 | let ic = open_in filename in 43 | let rec read_loop () = 44 | try 45 | let row = input_line ic in 46 | row :: read_loop () 47 | with End_of_file -> 48 | [] 49 | in 50 | let result = read_loop () in 51 | close_in ic; 52 | result 53 | ``` 54 | 55 | The function `read_file` reads all the lines of a file and returns them as a list of strings. 56 | -------------------------------------------------------------------------------- /material/w09-side_effects/w09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w09-side_effects/w09.pdf -------------------------------------------------------------------------------- /material/w09-side_effects/w09.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w09-side_effects/w09.pptx -------------------------------------------------------------------------------- /material/w10-modules/10-modules.md: -------------------------------------------------------------------------------- 1 | # Week 10: Modules 2 | 3 | In Ocaml, a module is a collection of types, values, and functions. Modules are used to organize code and to avoid name clashes. Modules can be nested, and they can be parameterized by other modules. 4 | 5 | ## 10.1 Module Types 6 | 7 | A module type is a specification of the types, values, and functions that a module must provide. Module types are used to specify the interface of a module. A module type can be parameterized by other module types. 8 | 9 | A module type is defined using the `module type` keyword. For example, the following module type specifies that a module must provide a type `t` and a function `f`: 10 | 11 | ```ocaml 12 | module type ModType = sig 13 | type t 14 | val f : t -> t 15 | end 16 | ``` 17 | 18 | In Java, a module type is similar to an interface with a generic type parameter. 19 | 20 | ```java 21 | interface ModType { 22 | T f(T x); 23 | } 24 | ``` 25 | 26 | ## 10.2 Module 27 | 28 | A Module is a similar to a class in Java. It can also implement a module type. A module can be defined using the `module` keyword. For example, the following module implements the module type `ModType`: 29 | 30 | ```ocaml 31 | module Mod : ModType with type t = int = struct 32 | type t = int 33 | let f x = x + 1 34 | end 35 | ``` 36 | 37 | In Java, a module is similar to a class that implements an interface. 38 | 39 | ```java 40 | class Mod implements ModType { 41 | public Integer f(Integer x) { 42 | return x + 1; 43 | } 44 | } 45 | ``` 46 | 47 | We can call the function `f` in the module `Mod` as follows: 48 | 49 | ```ocaml 50 | Mod.f 1 51 | (* returns 2 *) 52 | ``` 53 | 54 | ## 10.3 Functors 55 | 56 | A functor is a function that takes a module as an argument and returns a module. A functor can be defined in the following way: 57 | 58 | ```ocaml 59 | module Functor (M : ModType with type t = int) : ModType with type t = M.t = struct 60 | type t = M.t 61 | let f x = M.f (M.f x) 62 | end 63 | ``` 64 | 65 | This particular functor takes a module of type `ModType` and returns a module of type `ModType`. The returned Module differs from the input module in that the function `f` is applied twice. 66 | 67 | It can be used in the following way: 68 | 69 | ```ocaml 70 | module Mod2 = Functor(Mod) 71 | 72 | Mod2.f 1 73 | (* returns 3 , because inc is applied twice*) 74 | ``` 75 | -------------------------------------------------------------------------------- /material/w10-modules/code/Java/MapDemo.java: -------------------------------------------------------------------------------- 1 | import map.IntIntMap; 2 | import map.IntOrderedPrintable; 3 | import map.IntStringMap; 4 | import map.StringPrintable; 5 | 6 | public class MapDemo { 7 | 8 | public static void main(String[] args) { 9 | System.out.println("#Int-String-Map demo\n"); 10 | int_string_demo(args); 11 | 12 | System.out.println("\n#Int-Int-Map demo\n"); 13 | int_int_demo(args); 14 | } 15 | 16 | public static void int_string_demo(String[] args) { 17 | var my_map = new IntStringMap(); 18 | 19 | my_map.set(new IntOrderedPrintable(1), new StringPrintable("one")); 20 | my_map.set(new IntOrderedPrintable(2), new StringPrintable("two")); 21 | my_map.set(new IntOrderedPrintable(3), new StringPrintable("three")); 22 | 23 | System.out.println("##Printing the map"); 24 | 25 | System.out.println(my_map.to_string()); 26 | 27 | System.out.println("##Getting elements from the map"); 28 | 29 | System.out.println("searching for 2: " + my_map.get(new IntOrderedPrintable(2)).t); 30 | } 31 | 32 | // ##Printing the map 33 | // { 1 -> "one", 2 -> "two", 3 -> "three" } 34 | // ##Getting elements from the map 35 | // searching for 2: two 36 | 37 | public static void int_int_demo(String[] args) { 38 | var my_map = new IntIntMap(); 39 | 40 | my_map.set(new IntOrderedPrintable(1), new IntOrderedPrintable(5)); 41 | my_map.set(new IntOrderedPrintable(2), new IntOrderedPrintable(23)); 42 | my_map.set(new IntOrderedPrintable(3), new IntOrderedPrintable(62)); 43 | 44 | System.out.println("##Printing the map"); 45 | 46 | System.out.println(my_map.to_string()); 47 | 48 | System.out.println("##Getting elements from the map"); 49 | 50 | System.out.println("searching for 2: " + my_map.get(new IntOrderedPrintable(2)).t); 51 | } 52 | 53 | // ##Printing the map 54 | // { 1 -> 5, 2 -> 23, 3 -> 62 } 55 | // ##Getting elements from the map 56 | // searching for 2: 23 57 | } -------------------------------------------------------------------------------- /material/w10-modules/code/Java/map/BinaryTreeMap.java: -------------------------------------------------------------------------------- 1 | package map; 2 | // Define a generic class BinaryTreeMap that implements Map with a binary tree 3 | 4 | // In Ocaml, we would write: 5 | /* 6 | open LibPrintable 7 | open LibOrderedPrintable 8 | open LibMap 9 | 10 | module BinaryTreeMap = 11 | functor 12 | (K : OrderedPrintable) 13 | (V : Printable) 14 | -> 15 | struct 16 | type key = K.t 17 | type value = V.t 18 | type t = Empty | Node of key * value * t * t 19 | 20 | let empty = Empty 21 | 22 | let rec to_list = function 23 | | Empty -> [] 24 | | Node (k, v, l, r) -> to_list l @ ((k, v) :: to_list r) 25 | 26 | let rec set k v = function 27 | | Empty -> Node (k, v, Empty, Empty) 28 | | Node (k', v', l, r) -> 29 | let diff = K.compare k k' in 30 | if diff < 0 then Node (k', v', set k v l, r) 31 | else if diff > 0 then Node (k', v', l, set k v r) 32 | else Node (k', v, l, r) 33 | 34 | let rec get_opt k = function 35 | | Empty -> None 36 | | Node (k', v, l, r) -> 37 | let diff = K.compare k k' in 38 | if diff < 0 then get_opt k l 39 | else if diff > 0 then get_opt k r 40 | else Some v 41 | 42 | let get k m = 43 | Option.fold 44 | ~none:(fun _ -> raise Not_found) 45 | ~some:(fun x _ -> x) 46 | (get_opt k m) () 47 | 48 | let to_string m = 49 | List.map 50 | (fun (k, v) -> K.to_string k ^ " -> " ^ V.to_string v) 51 | (to_list m) 52 | |> String.concat ", " 53 | |> fun s -> "{ " ^ s ^ " }" (* Printf.sprintf "{ %s }" *) 54 | end 55 | */ 56 | 57 | import java.util.List; 58 | import java.util.Optional; 59 | import java.util.stream.Collectors; 60 | import java.util.stream.Stream; 61 | 62 | public class BinaryTreeMap implements Map { 63 | 64 | class t { 65 | K key; 66 | V value; 67 | t left; 68 | t right; 69 | 70 | t(K key, V value, t left, t right) { 71 | this.key = key; 72 | this.value = value; 73 | this.left = left; 74 | this.right = right; 75 | } 76 | } 77 | 78 | t root = null; 79 | 80 | @Override 81 | public V get(K key) { 82 | return get_opt(key).orElseThrow(() -> new RuntimeException("Key not found")); 83 | } 84 | 85 | @Override 86 | public void set(K key, V value) { 87 | root = setNode(root, key, value); 88 | } 89 | 90 | @Override 91 | public Optional get_opt(K key) { 92 | return findOptNode(root, key).map(n -> n.value); 93 | } 94 | 95 | @Override 96 | public String to_string() { 97 | var res = toList().stream() 98 | .map(p -> p.first.to_string(p.first.getT()) + " -> " + p.second.to_string(p.second.getT())) 99 | .collect(Collectors.joining(", ")); 100 | 101 | return "{ " + res + " }"; 102 | } 103 | 104 | @Override 105 | public List> toList() { 106 | return createList(root); 107 | } 108 | 109 | // 110 | // Helper methods 111 | // 112 | private Optional findOptNode(t root, K key) { 113 | if (root == null) { 114 | return Optional.empty(); 115 | } 116 | int diff = key.compare(key.getT(), root.key.getT()); 117 | if (diff < 0) { 118 | return findOptNode(root.left, key); 119 | } else if (diff > 0) { 120 | return findOptNode(root.right, key); 121 | } else { 122 | return Optional.of(root); 123 | } 124 | } 125 | 126 | private t setNode(t node, K key, V value) { 127 | if (node == null) { 128 | return new t(key, value, null, null); 129 | } 130 | 131 | int cmp = key.compare(key.getT(), node.key.getT()); 132 | if (cmp < 0) { 133 | node.left = setNode(node.left, key, value); 134 | } else if (cmp > 0) { 135 | node.right = setNode(node.right, key, value); 136 | } else { 137 | node.value = value; 138 | } 139 | 140 | return node; 141 | } 142 | 143 | private List> createList(t node) { 144 | if (node == null) { 145 | return List.of(); 146 | } 147 | 148 | var left = createList(node.left); 149 | var right = createList(node.right); 150 | 151 | return Stream 152 | .concat(left.stream(), Stream.concat(Stream.of(new Pair(node.key, node.value)), right.stream())) 153 | .collect(Collectors.toList()); 154 | } 155 | 156 | } -------------------------------------------------------------------------------- /material/w10-modules/code/Java/map/IntIntMap.java: -------------------------------------------------------------------------------- 1 | package map; 2 | // Instantiate the generic BinaryTreeMap class with the IntOrderedPrintable class 3 | 4 | // In Ocaml, we would write: 5 | /* 6 | open LibBinaryTreeMap 7 | open LibIntOrderedPrintable 8 | 9 | module IntIntMap = BinaryTreeMap (IntOrderedPrintable) (IntOrderedPrintable) 10 | */ 11 | 12 | public class IntIntMap extends BinaryTreeMap { 13 | 14 | } -------------------------------------------------------------------------------- /material/w10-modules/code/Java/map/IntOrderedPrintable.java: -------------------------------------------------------------------------------- 1 | package map; 2 | // Define a class IntOrderedPrintable that implements OrderedPrintable 3 | 4 | // In Ocaml, we would write: 5 | /* 6 | module IntOrderedPrintable : OrderedPrintable with type t = int = struct 7 | type t = int 8 | let to_string t = string_of_int t 9 | let compare = compare 10 | end 11 | */ 12 | 13 | public class IntOrderedPrintable implements OrderedPrintable { 14 | 15 | public Integer t; 16 | 17 | public IntOrderedPrintable(Integer t) { 18 | this.t = t; 19 | } 20 | 21 | public String to_string(Integer t) { 22 | return Integer.toString(t); 23 | } 24 | 25 | public int compare(Integer t1, Integer t2) { 26 | return Integer.compare(t1, t2); 27 | } 28 | 29 | public Integer getT() { 30 | return t; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /material/w10-modules/code/Java/map/IntStringMap.java: -------------------------------------------------------------------------------- 1 | package map; 2 | // Instantiate the generic BinaryTreeMap class with the IntOrderedPrintable class and the StringPrintable class 3 | 4 | // In Ocaml, we would write: 5 | /* 6 | open LibBinaryTreeMap 7 | open LibStringPrintable 8 | open LibIntOrderedPrintable 9 | 10 | module IntStringMap = BinaryTreeMap (IntOrderedPrintable) (StringPrintable) 11 | */ 12 | 13 | public class IntStringMap extends BinaryTreeMap { 14 | 15 | } -------------------------------------------------------------------------------- /material/w10-modules/code/Java/map/Map.java: -------------------------------------------------------------------------------- 1 | package map; 2 | 3 | // Define a generic interface Map with a method get 4 | 5 | //In Ocaml, we would write: 6 | /* 7 | module type Map = sig 8 | type key 9 | type value 10 | type t 11 | 12 | val empty : t 13 | val set : key -> value -> t -> t 14 | val get : key -> t -> value 15 | val get_opt : key -> t -> value option 16 | (* val clear : key -> t -> t *) 17 | val to_string : t -> string 18 | val to_list : t -> (key * value) list 19 | end 20 | */ 21 | 22 | //Note that in java we dont have a type t, because the class name Map is the type t. And since Java is object oriented, we never have to pass around the type t, because we can always call the methods on the object itself. 23 | 24 | import java.util.List; 25 | import java.util.Optional; 26 | 27 | public interface Map { 28 | 29 | void set(K key, V value); 30 | 31 | V get(K key); 32 | 33 | Optional get_opt(K key); 34 | 35 | String to_string(); 36 | 37 | List> toList(); 38 | } -------------------------------------------------------------------------------- /material/w10-modules/code/Java/map/OrderedPrintable.java: -------------------------------------------------------------------------------- 1 | package map; 2 | // Define a generic interface OrderedPrintable that extends Printable with a method compare 3 | 4 | // In Ocaml, we would write: 5 | /* 6 | open LibPrintable 7 | 8 | module type OrderedPrintable = sig 9 | include Printable 10 | 11 | val compare : t -> t -> int 12 | end 13 | */ 14 | 15 | public interface OrderedPrintable extends Printable { 16 | int compare(T t1, T t2); 17 | } 18 | -------------------------------------------------------------------------------- /material/w10-modules/code/Java/map/Pair.java: -------------------------------------------------------------------------------- 1 | package map; 2 | 3 | public class Pair { 4 | 5 | T1 first; 6 | T2 second; 7 | 8 | public Pair(T1 first, T2 second) { 9 | this.first = first; 10 | this.second = second; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /material/w10-modules/code/Java/map/Printable.java: -------------------------------------------------------------------------------- 1 | package map; 2 | // Define a generic interface Printable with a method to_string 3 | 4 | // In Ocaml, we would write: 5 | /* 6 | module type Printable = sig 7 | type t 8 | val to_string : t -> string 9 | end 10 | */ 11 | 12 | public interface Printable { 13 | 14 | String to_string(T t); 15 | 16 | T getT(); 17 | } 18 | -------------------------------------------------------------------------------- /material/w10-modules/code/Java/map/StringPrintable.java: -------------------------------------------------------------------------------- 1 | package map; 2 | 3 | // Define a class StringPrintable that implements Printable 4 | // The to_string method should return the quoted string 5 | 6 | // In Ocaml, we would write: 7 | /* 8 | open LibPrintable 9 | 10 | module StringPrintable : Printable with type t = string = struct 11 | type t = string 12 | 13 | let to_string : t -> string = fun t -> "\"" ^ t ^ "\"" 14 | end 15 | 16 | */ 17 | 18 | public class StringPrintable implements Printable { 19 | 20 | public String t; 21 | 22 | public StringPrintable(String t) { 23 | this.t = t; 24 | } 25 | 26 | public String to_string(String t) { 27 | return "\"" + t + "\""; 28 | } 29 | 30 | public String getT() { 31 | return t; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/.gitattributes: -------------------------------------------------------------------------------- 1 | # Handle line endings automatically for files detected as text 2 | # and leave all files detected as binary untouched. 3 | * text=auto 4 | 5 | # 6 | # The above will handle all files NOT found below 7 | # 8 | # These files are text and should be normalized (Convert crlf => lf) 9 | *.bash text eol=lf 10 | *.css text diff=css 11 | *.df text 12 | *.htm text diff=html 13 | *.html text diff=html 14 | *.hs text 15 | *.java text diff=java 16 | *.js text 17 | *.json text 18 | *.jsp text 19 | *.jspf text 20 | *.jspx text 21 | *.properties text 22 | *.sh text eol=lf 23 | *.tld text 24 | *.txt text 25 | *.tag text 26 | *.tagx text 27 | *.xml text 28 | *.yml text 29 | 30 | # These files are binary and should be left untouched 31 | # (binary is a macro for -text -diff) 32 | *.class binary 33 | *.dll binary 34 | *.ear binary 35 | *.gif binary 36 | *.ico binary 37 | *.jar binary 38 | *.jpg binary 39 | *.jpeg binary 40 | *.png binary 41 | *.so binary 42 | *.war binary 43 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/.gitignore: -------------------------------------------------------------------------------- 1 | # https://raw.githubusercontent.com/github/gitignore/master/OCaml.gitignore 2 | 3 | *.annot 4 | *.cmo 5 | *.cma 6 | *.cmi 7 | *.a 8 | *.o 9 | *.cmx 10 | *.cmxs 11 | *.cmxa 12 | 13 | # ocamlbuild working directory 14 | _build/ 15 | 16 | # ocamlbuild targets 17 | *.byte 18 | *.native 19 | 20 | # oasis generated files 21 | setup.data 22 | setup.log 23 | 24 | # Merlin configuring file for Vim and Emacs 25 | .merlin 26 | 27 | # Dune generated files 28 | *.install 29 | 30 | # Local OPAM switch 31 | _opam/ -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/.ocamlformat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w10-modules/code/OCaml/.ocamlformat -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/binarytreemap/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name libBinaryTreeMap) 4 | (libraries libMap libOrderedPrintable libPrintable common) 5 | (flags 6 | (:standard -warn-error -27-33))) 7 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/binarytreemap/libBinaryTreeMap.ml: -------------------------------------------------------------------------------- 1 | open LibPrintable 2 | open LibOrderedPrintable 3 | open LibMap 4 | 5 | module BinaryTreeMap = 6 | functor 7 | (K : OrderedPrintable) 8 | (V : Printable) 9 | -> 10 | struct 11 | type key = K.t 12 | type value = V.t 13 | type t = Empty | Node of key * value * t * t 14 | 15 | let empty = Empty 16 | 17 | let rec to_list = function 18 | | Empty -> [] 19 | | Node (k, v, l, r) -> to_list l @ ((k, v) :: to_list r) 20 | 21 | let rec set k v = function 22 | | Empty -> Node (k, v, Empty, Empty) 23 | | Node (k', v', l, r) -> 24 | let diff = K.compare k k' in 25 | if diff < 0 then Node (k', v', set k v l, r) 26 | else if diff > 0 then Node (k', v', l, set k v r) 27 | else Node (k', v, l, r) 28 | 29 | let rec get_opt k = function 30 | | Empty -> None 31 | | Node (k', v, l, r) -> 32 | let diff = K.compare k k' in 33 | if diff < 0 then get_opt k l 34 | else if diff > 0 then get_opt k r 35 | else Some v 36 | 37 | let get k m = 38 | Option.fold 39 | ~none:(fun _ -> raise Not_found) 40 | ~some:(fun x _ -> x) 41 | (get_opt k m) () 42 | 43 | (* let rec clear k = function Empty -> Empty 44 | | Node (k', v, l, r) -> 45 | let rec remove_max = function Empty -> failwith "unreachable" 46 | | Node (k, v, l, Empty) -> k, v, l 47 | | Node (k, v, l, r) -> let k', v', r' = remove_max r in k', v', Node (k, v, l, r') 48 | in 49 | let diff = K.compare k k' in 50 | if diff < 0 then Node (k', v, clear k l, r) 51 | else if diff > 0 then Node (k', v, l, clear k r) 52 | else if l = Empty then r 53 | else let max_k, max_v, max_l = remove_max l in 54 | Node (max_k, max_v, max_l, r) *) 55 | 56 | let to_string m = 57 | List.map 58 | (fun (k, v) -> K.to_string k ^ " -> " ^ V.to_string v) 59 | (to_list m) 60 | |> String.concat ", " 61 | |> fun s -> "{ " ^ s ^ " }" (* Printf.sprintf "{ %s }" *) 62 | end 63 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/common/common.ml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w10-modules/code/OCaml/common/common.ml -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/common/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name common) 4 | (flags 5 | (:standard -warn-error -27-33))) 6 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/demo.ml: -------------------------------------------------------------------------------- 1 | open LibIntStringMap 2 | 3 | let my_map = IntStringMap.empty 4 | 5 | (* Insert *) 6 | let my_map = IntStringMap.set 1 "one" my_map 7 | let my_map = IntStringMap.set 2 "two" my_map 8 | let my_map = IntStringMap.set 3 "three" my_map 9 | 10 | (* Read *) 11 | 12 | let list = IntStringMap.to_list my_map 13 | 14 | (* val list : (int * string) list = [(1, "one"); (2, "two"); (3, "three")] *) 15 | let string = IntStringMap.to_string my_map 16 | 17 | (* val string : string = "{ 1 -> \"one\", 2 -> \"two\", 3 -> \"three\" }" *) 18 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name demo) 4 | (libraries libIntStringMap common) 5 | (flags 6 | (:standard -warn-error -27-33))) 7 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 2.0) 2 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/intintmap/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name libIntIntMap) 4 | (libraries libBinaryTreeMap libIntOrderedPrintable libOrderedPrintable libMap common) 5 | (flags 6 | (:standard -warn-error -27-33))) 7 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/intintmap/libIntIntMap.ml: -------------------------------------------------------------------------------- 1 | open LibBinaryTreeMap 2 | open LibIntOrderedPrintable 3 | 4 | module IntIntMap = BinaryTreeMap (IntOrderedPrintable) (IntOrderedPrintable) 5 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/intorderedprintable/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name libIntOrderedPrintable) 4 | (libraries libOrderedPrintable common) 5 | (flags 6 | (:standard -warn-error -27-33))) 7 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/intorderedprintable/libIntOrderedPrintable.ml: -------------------------------------------------------------------------------- 1 | open LibOrderedPrintable 2 | 3 | module IntOrderedPrintable : OrderedPrintable with type t = int = struct 4 | type t = int 5 | 6 | let to_string t = string_of_int t 7 | let compare = compare 8 | end 9 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/intstringmap/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name libIntStringMap) 4 | (libraries libBinaryTreeMap libStringPrintable libIntOrderedPrintable libOrderedPrintable libMap common) 5 | (flags 6 | (:standard -warn-error -27-33))) 7 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/intstringmap/libIntStringMap.ml: -------------------------------------------------------------------------------- 1 | open LibBinaryTreeMap 2 | open LibStringPrintable 3 | open LibIntOrderedPrintable 4 | module IntStringMap = BinaryTreeMap (IntOrderedPrintable) (StringPrintable) 5 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/map/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name libMap) 4 | (libraries common) 5 | (flags 6 | (:standard -warn-error -27-33))) 7 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/map/libMap.ml: -------------------------------------------------------------------------------- 1 | module type Map = sig 2 | type key 3 | type value 4 | type t 5 | 6 | val empty : t 7 | val set : key -> value -> t -> t 8 | val get : key -> t -> value 9 | val get_opt : key -> t -> value option 10 | (* val clear : key -> t -> t *) 11 | val to_string : t -> string 12 | val to_list : t -> (key * value) list 13 | end 14 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/orderedprintable/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name libOrderedPrintable) 4 | (libraries libPrintable common) 5 | (flags 6 | (:standard -warn-error -27-33))) 7 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/orderedprintable/libOrderedPrintable.ml: -------------------------------------------------------------------------------- 1 | open LibPrintable 2 | 3 | module type OrderedPrintable = sig 4 | include Printable 5 | 6 | val compare : t -> t -> int 7 | end 8 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/printable/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name libPrintable) 4 | (libraries common) 5 | (flags 6 | (:standard -warn-error -27-33))) 7 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/printable/libPrintable.ml: -------------------------------------------------------------------------------- 1 | module type Printable = sig 2 | type t 3 | val to_string : t -> string 4 | end 5 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/stringprintable/dune: -------------------------------------------------------------------------------- 1 | ; auto-generated by deps.sh 2 | (library 3 | (name libStringPrintable) 4 | (libraries libPrintable common) 5 | (flags 6 | (:standard -warn-error -27-33))) 7 | -------------------------------------------------------------------------------- /material/w10-modules/code/OCaml/stringprintable/libStringPrintable.ml: -------------------------------------------------------------------------------- 1 | open LibPrintable 2 | 3 | module StringPrintable : Printable with type t = string = struct 4 | type t = string 5 | 6 | let to_string : t -> string = fun t -> "\"" ^ t ^ "\"" 7 | end 8 | -------------------------------------------------------------------------------- /material/w10-modules/w10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w10-modules/w10.pdf -------------------------------------------------------------------------------- /material/w10-modules/w10.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w10-modules/w10.pptx -------------------------------------------------------------------------------- /material/w11-big_step/11-big_step.md: -------------------------------------------------------------------------------- 1 | # Week 11: Big Step Semantics 2 | 3 | Big step semantics is a way to define the semantics of a programming language by recursively reducing the program-expression to a value. The reduction is done in a top-down manner, starting from the root of the expression tree. The reduction stops when the expression is reduced to a value. 4 | 5 | ## Big Step for OCaml Expressions 6 | 7 | Now we are going to define the big step semantics for OCaml expressions. 8 | 9 | ### Tuple 10 | 11 | A tuple is a sequence of expressions separated by commas and enclosed in parentheses. The big step semantics for a tuple is to evaluate each expression in the tuple in order, and return a tuple of the values of the expressions. 12 | 13 | ```ocaml 14 | (E1, E2, ..., En) => (V1, V2, ..., Vn) 15 | ``` 16 | 17 | where `E1, E2, ..., En` are expressions, `V1, V2, ..., Vn` are values, and `n >= 0`. 18 | 19 | ![Tuple Evaluation](material/w11-big_step/images/image1.png) 20 | 21 | ### List 22 | 23 | Lists work similarly to tuples. The big step semantics for a list is to decompose the list into its head and tail, evaluate the head and tail, and return a list with the evaluated head and tail. 24 | 25 | ```ocaml 26 | H::T => V::W 27 | ``` 28 | 29 | where `H` is an expression, `T` is a list, `V` is a value, and `W` is a list. 30 | 31 | ![List Evalueation](material/w11-big_step/images/image2.png) 32 | 33 | ### Global Definition 34 | 35 | A global definition is a definition of a value at the top level of a program. The big step semantics for a global definition is to look up the value of the expression, and return its value. 36 | 37 | ![Global Definition](material/w11-big_step/images/image3.png) 38 | 39 | ### Local Definition 40 | 41 | A local definition is a definition of a value inside a `let` expression. The big step semantics for a local definition is to evaluate the expression, and then substitute the value of the expression for the variable in the body of the `let` expression. 42 | 43 | ![Local Definition](material/w11-big_step/images/image4.png) 44 | 45 | ### Function Call 46 | 47 | In order to evaluate a function call, we need to evaluate the function expression and the argument expression. Then we substitute the value of the argument expression for the parameter in the body of the function expression. 48 | 49 | ![Function Call](material/w11-big_step/images/image5.png) 50 | 51 | ### Pattern Matching 52 | 53 | The big step semantics for pattern matching is to evaluate the expression, and then match the value of the expression with the patterns. If the value matches a pattern, then we substitute the value of the expression for the variable in the body of the pattern. 54 | 55 | ![Pattern Matching](material/w11-big_step/images/image6.png) 56 | 57 | ### Built-in Operators 58 | 59 | Built in operators cannot be evaluated directly, we need to compose them into their mathematical expressions first. For example, `1 + 2` is composed of the integer `1`, the operator `+`, and the integer `2`. The big step semantics for a built-in operator is to evaluate the expressions in the operator, and then apply the operator to the values of the expressions. 60 | 61 | ![Built-in Operators](material/w11-big_step/images/image7.png) 62 | 63 | ## Example 64 | 65 | In this example, an expression using recursive functions will be evaluated: 66 | 67 | ```ocaml 68 | let rec f = fun x -> x + 1 69 | and s = fun y -> y * y 70 | ``` 71 | 72 | We are going to calculate the value of the expression: 73 | 74 | ```ocaml 75 | f 16 + s 2 76 | ``` 77 | 78 | ![Example Big Step Program](material/w11-big_step/images/image8.png) 79 | 80 | Using the rules defined above, we can evaluate the expression and arrive at the value `21`. 81 | -------------------------------------------------------------------------------- /material/w11-big_step/images/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/images/image1.png -------------------------------------------------------------------------------- /material/w11-big_step/images/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/images/image2.png -------------------------------------------------------------------------------- /material/w11-big_step/images/image3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/images/image3.png -------------------------------------------------------------------------------- /material/w11-big_step/images/image4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/images/image4.png -------------------------------------------------------------------------------- /material/w11-big_step/images/image5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/images/image5.png -------------------------------------------------------------------------------- /material/w11-big_step/images/image6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/images/image6.png -------------------------------------------------------------------------------- /material/w11-big_step/images/image7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/images/image7.png -------------------------------------------------------------------------------- /material/w11-big_step/images/image8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/images/image8.png -------------------------------------------------------------------------------- /material/w11-big_step/w11.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/w11.pdf -------------------------------------------------------------------------------- /material/w11-big_step/w11.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w11-big_step/w11.pptx -------------------------------------------------------------------------------- /material/w12-equational_reasoning/12-equational_reasoning.md: -------------------------------------------------------------------------------- 1 | # Week 12: Equational Reasoning 2 | 3 | Equational reasoning is a powerful technique for proving properties of programs. We mostly use it to verify that a function behaves as expected, the main idea is to repeatedly substitute equal expressions and to perform simplifications until we show that the result is the expected one. 4 | We often do this by performing induction on the structure of the input. 5 | 6 | An important aspect to note is that if a function has an auxiliary variable. For example: 7 | 8 | ```ocaml 9 | let rec fact_aux n acc = 10 | if n = 0 then acc 11 | else fact_aux (n - 1) (n * acc) 12 | 13 | let fact_iter n = fact_aux n 1 14 | ``` 15 | 16 | During the induction step it is often necessary to prove a generalized version of the function for the proof to go through. In this case we would need to prove that `fact_aux n acc = acc * fact n`. 17 | 18 | ```ocaml 19 | let fact_aux n acc = acc * fact n 20 | ``` 21 | 22 | ## Example: Prove that `fact n = n * fact (n - 1)` 23 | 24 | Let fact be defined as: 25 | 26 | ```ocaml 27 | let rec fact n = match n with 0 -> 1 28 | | n -> n * fact (n - 1) 29 | ``` 30 | 31 | ```ocaml 32 | We want to prove that: 33 | fact_iter n = n * fact n 34 | Which corresponds to: 35 | fact_aux n 1 = n * fact n 36 | 37 | As mentioned before, we need to prove a generalized version of the function: 38 | fact_aux n acc = acc * fact n 39 | 40 | Proof of the generalized version: 41 | 42 | Base case n = 0: 43 | fact_aux 0 acc 44 | (fact_aux) = if 0 = 0 then acc else fact_aux (0 - 1) (0 * acc) 45 | (match) = acc 46 | (arith) = acc 47 | (match) = acc * 1 48 | (fact) = acc * (match 0 with 0 -> 1 | n -> n * fact (n - 1)) 49 | = acc * fact 0 50 | 51 | 52 | Induction step n+1: (IH: fact_aux n acc = acc * fact n) 53 | fact_aux (n+1) acc 54 | (fact_aux) = if (n+1) = 0 then acc else fact_aux ((n+1) - 1) ((n+1) * acc) 55 | (match) = fact_aux ((n+1) - 1) ((n+1) * acc) 56 | (arith) = fact_aux n ((n+1) * acc) 57 | (IH) = (n+1) * acc * fact n 58 | (arith) = (n+1) * acc * fact ((n+1) - 1) 59 | (match) = acc * ((n+1) * fact ((n+1) - 1)) 60 | (fact) = acc * (match n+1 with 0 -> 1 | n -> n * fact (n - 1)) 61 | = acc * fact (n+1) 62 | ``` 63 | 64 | The proof of the generalized version is complete, this means that: 65 | 66 | ```ocaml 67 | fact_aux n acc = acc * fact n 68 | ``` 69 | 70 | To proof the original statement we need instantiate the generalized version with `acc = 1`: 71 | 72 | ```ocaml 73 | fact_aux n 1 74 | (#) = 1 * fact n 75 | (arith) = fact n 76 | ``` 77 | 78 | Which completes the proof. We can be sure that `fact n = n * fact (n - 1)` and that the helper function `fact_aux` is correct. 79 | -------------------------------------------------------------------------------- /material/w12-equational_reasoning/proofs/exam_template.txt: -------------------------------------------------------------------------------- 1 | Generalized statement (*) (if necessary): <...> 2 | --- 3 | Base Case: 4 | Statement being proven in base case: <...> 5 | Proof of base case: 6 | <...> 7 | --- 8 | Inductive Step: 9 | Induction hypothesis (or hypotheses): <...> 10 | Statement being proved in inductive step: <...> 11 | Proof of inductive step: 12 | <...> 13 | --- 14 | Instantiation of generalization (if necessary): 15 | <...> 16 | --- 17 | QED -------------------------------------------------------------------------------- /material/w12-equational_reasoning/proofs/t01.txt: -------------------------------------------------------------------------------- 1 | let rec fact n = match n with 0 -> 1 2 | | n -> n * fact (n-1) 3 | 4 | 5 | let rec fact_aux acc n = match n with 0 -> acc 6 | | n -> fact_aux (n*acc) (n-1) 7 | 8 | let fact_iter n = fact_aux 1 n 9 | 10 | ################################################ 11 | 12 | To prove: 13 | fact_iter n = fact n 14 | 15 | Adaptation: 16 | fact_aux 1 n = fact n 17 | 18 | Generalization: 19 | fact_aux acc n = acc * fact n 20 | 21 | 22 | 23 | Proof by Induction on n 24 | 25 | Base: n = 0 26 | 27 | fact_aux acc 0 28 | (fact_aux) = match 0 with 0 -> acc | n -> fact_aux (n*acc) (n-1) 29 | (match) = acc 30 | (arith) = acc 31 | (match) = acc * 1 32 | (fact) = acc * match 0 with 0 -> 1 | n -> n * fact (n-1) 33 | = acc * fact 0 34 | 35 | 36 | Hypothesis: (*) 37 | fact_aux acc n = acc * fact n 38 | 39 | Step: 40 | 41 | fact_aux acc (n+1) 42 | (fact_aux) = match (n+1) with 0 -> acc | n -> fact_aux (n*acc) (n-1) 43 | (match) = fact_aux ((n+1)*acc) ((n+1)-1) 44 | (arith) = fact_aux ((n+1)*acc) n 45 | (I.H) = ((n+1)*acc) * fact n 46 | (arith) = acc * (n+1) * fact n 47 | (arith) = acc * (n+1) * fact n 48 | (match) = acc * (n+1) * fact ((n+1)-1) 49 | (fact) = acc * match (n+1) with 0 -> 1 | n -> n * fact (n-1) 50 | = acc * fact (n+1) 51 | 52 | 53 | 54 | Trace Back: 55 | 56 | fact_iter n 57 | (fact_iter) = fact_aux 1 n 58 | (*) = 1 * fact n 59 | (arith) = fact n 60 | = fact n 61 | -------------------------------------------------------------------------------- /material/w12-equational_reasoning/proofs/t02.txt: -------------------------------------------------------------------------------- 1 | let rec summa l = match l with 2 | | [] -> 0 3 | | h :: t -> h + summa t 4 | 5 | let rec sum l a = match l with 6 | | [] -> a 7 | | h :: t -> sum t (h + a) 8 | 9 | let rec mul i j a = match i <= 0 with 10 | | true -> a 11 | | false -> mul (i - 1) j (j + a) 12 | 13 | ################################################ 14 | 15 | To prove: 16 | mul c (sum l 0) 0 = c * summa l 17 | 18 | Generalization: 19 | * mul c (sum l acc1) acc2 = acc2 + c * (acc1 + summa l) 20 | 21 | 22 | ================== Lemma 1 ================================= 23 | 24 | Lemma 1: 25 | sum l acc1 = acc1 + summa l 26 | 27 | Proof of * by Induction on l 28 | 29 | Base: l = [] 30 | 31 | sum [] acc1 32 | (rules) = <....> 33 | = acc1 + summa [] 34 | 35 | Hypothesis: 36 | sum l acc1 = acc1 + summa l 37 | 38 | Step: 39 | 40 | sum (x :: xs) acc1 41 | (rules) = <....> 42 | = acc1 + summa (x :: xs) 43 | 44 | ================== End Lemma 1 ============================= 45 | 46 | 47 | Proof of initial goal by Induction on c: 48 | To Proof: mul c (sum l acc1) acc2 = acc2 + c * (acc1 + summa l) 49 | 50 | Base: c = 0 51 | 52 | mul 0 (sum l acc1) acc2 53 | (rules) = <...> 54 | = acc2 + 0 * (acc1 + summa l) 55 | 56 | 57 | 58 | Hypothesis: (Does it hold?) 59 | mul c (sum l acc1) acc2 = acc2 + c * (acc1 + summa l) 60 | 61 | Step: 62 | 63 | mul (c + 1) (sum l acc1) acc2 64 | (rules) = <...> 65 | = acc2 + (c + 1) * (acc1 + summa l) 66 | 67 | 68 | 69 | Trace Back: 70 | 71 | mul c (sum l 0) 0 72 | (rules) = (...) 73 | = c * summa l 74 | -------------------------------------------------------------------------------- /material/w12-equational_reasoning/proofs/t03.txt: -------------------------------------------------------------------------------- 1 | type tree = Node of tree * tree | Empty 2 | 3 | let rec nodes t = match t with Empty -> 0 4 | | Node (l,r) -> 1 + (nodes l) + (nodes r) 5 | 6 | let rec count t = 7 | let rec aux t a = match t with Empty -> a 8 | | Node (l,r) -> aux r (aux l (a+1)) 9 | in 10 | aux t 0 11 | 12 | ################################################ 13 | 14 | To prove: 15 | nodes t = count t 16 | 17 | Adaptation: 18 | nodes t = aux t 0 19 | 20 | Generalization: 21 | acc + nodes t = aux t acc 22 | 23 | 24 | 25 | Proof of the generalization (by induction on t): 26 | 27 | Base: t = Empty 28 | 29 | acc + nodes Empty 30 | (nodes) = acc + match Empty with Empty -> 0 | Node (l,r) -> 1 + (nodes l) + (nodes r) 31 | (match) = acc + 0 32 | (arith) = acc 33 | (match) = acc 34 | (aux) = match Empty with Empty -> acc | Node (l,r) -> aux r (aux l (acc+1)) 35 | = aux Empty acc 36 | 37 | 38 | 39 | Hypothesis: 40 | acc + nodes t = aux t acc 41 | 42 | Step: 43 | 44 | acc + nodes (Node (a,b)) 45 | (nodes) = acc + match Node (a,b) with Empty -> 0 | Node (l,r) -> 1 + (nodes l) + (nodes r) 46 | (match) = (acc + 1) + (nodes a) + (nodes b) 47 | (I.H) = acc + 1 + nodes a + nodes b 48 | (I.H) = aux b (acc+1 + nodes a) 49 | (match) = aux b (aux a (acc+1)) 50 | (aux) = match Node (a,b) with Empty -> acc | Node (l,r) -> aux r (aux l (acc+1)) 51 | = aux (Node (a,b)) acc 52 | 53 | 54 | 55 | (*) 56 | => acc + nodes t = aux t acc 57 | 58 | 59 | Trace Back: 60 | 61 | nodes t 62 | (arith) = 0 + nodes t 63 | (*) = aux t 0 64 | 65 | (count) = aux t 0 66 | = count t 67 | -------------------------------------------------------------------------------- /material/w12-equational_reasoning/w12.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w12-equational_reasoning/w12.pdf -------------------------------------------------------------------------------- /material/w12-equational_reasoning/w12.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w12-equational_reasoning/w12.pptx -------------------------------------------------------------------------------- /material/w13-threads/13-threads.md: -------------------------------------------------------------------------------- 1 | # Week 13: Threads 2 | 3 | In ocaml we can use the `Thread` module to create threads. The `Thread` module provides a `create` function that takes a function and its arguments and runs it in a new thread. It returns a `Thread.t` object, which represents the handle to the thread. We can use the `join` function to wait for the thread to finish. 4 | 5 | ```ocaml 6 | let my_function sec = Thread.delay sec ; print_endline "Hello world!" ;; 7 | 8 | let t = Thread.create my_function 5.0 ;; 9 | Thread.join t ;; 10 | 11 | print_endline "Done!" ;; 12 | ``` 13 | 14 | This code will print "Hello world!" after 5 seconds. The main thread will wait for the thread to finish before printing "Done!", because of the `Thread.join` call. 15 | 16 | ## Returning values from threads 17 | 18 | As you can see above the `Thread.create` function returns a `Thread.t` object. So there is no direct way of accessing the return value of the thread. For this we use the `Event` module. The `Event` module provides a `new_channel` which can be used to create a communication channel between threads. 19 | 20 | It has two important methods: 21 | 22 | 1. `Event.send`: This method takes a channel and a value and sends the value to the channel. 23 | 2. `Event.receive`: This method takes a channel and attempts to receive a value from the channel 24 | 25 | We use the `Event.sync` method to wait for the value to be received at the other end of the channel (If we wrap it around a `Event.send` call). Or wait 26 | block until we can receive a value from the channel (If we wrap it around a `Event.receive` call). 27 | 28 | Note that this method blocks the thread until the underlying event is completed. 29 | 30 | ```ocaml 31 | let my_costly_function (x, response_channel) = 32 | (* Perform heavy calculations *) 33 | let result = x * x in 34 | Thread.delay 5.0 ; 35 | (* Wait for the response to be read by someone *) 36 | Event.sync (Event.send response_channel result) ;; 37 | 38 | let response_channel = Event.new_channel () ;; 39 | 40 | let t = Thread.create my_costly_function (5, response_channel) ;; 41 | 42 | (* Wait for the response to be sent by the other thread *) 43 | let result = Event.sync (Event.receive response_channel) ;; 44 | 45 | print_endline (string_of_int result) ;; 46 | ``` 47 | 48 | Using this we can retrieve the return value of the thread. Note that we can only send one value through the channel. 49 | -------------------------------------------------------------------------------- /material/w13-threads/code/blog_server.ml: -------------------------------------------------------------------------------- 1 | open Thread 2 | open Event 3 | 4 | type blog = string list 5 | type user = string 6 | type pass = string 7 | type message = Post of user * pass * string | Read of user * blog channel 8 | type t = message channel 9 | 10 | let start_server users = 11 | let (ch : message channel) = new_channel () in 12 | 13 | let rec main db = 14 | let get_blogs user = 15 | match List.assoc_opt user db with None -> [] | Some blogs -> blogs 16 | in 17 | 18 | let curr_message = sync (receive ch) in 19 | let new_db = 20 | match curr_message with 21 | | Post (u, p, t) -> 22 | if List.assoc_opt u users = Some p then 23 | (u, get_blogs u @ [ t ]) :: List.remove_assoc u db 24 | else db 25 | | Read (u, c) -> 26 | let blogs = get_blogs u in 27 | sync (send c blogs); 28 | db 29 | in 30 | 31 | main new_db 32 | in 33 | let _ = Thread.create main [] in 34 | ch 35 | 36 | let post s u p t = sync (send s (Post (u, p, t))) 37 | 38 | let read s u = 39 | let ch = new_channel () in 40 | sync (send s (Read (u, ch))); 41 | sync (receive ch) 42 | -------------------------------------------------------------------------------- /material/w13-threads/w13.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w13-threads/w13.pdf -------------------------------------------------------------------------------- /material/w13-threads/w13.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManuelLerchner/fpv-tutorial-SS23/5e04ba070338dad76d002d9dcfcc1d0eeda41c06/material/w13-threads/w13.pptx -------------------------------------------------------------------------------- /render.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir -p docs 3 | pandoc -V documentclass=report -V classoption=oneside -V geometry:vmargin=14.5mm -V lang:de --fail-if-warnings --output=docs/summary.pdf material/**/*.md 4 | 5 | # merge slides in material folder 6 | pdftk material/**/w*.pdf cat output docs/slides.pdf --------------------------------------------------------------------------------