├── .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 | [](https://github.com/ManuelLerchner/subject/actions/workflows/render.yml)
4 | [](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 | [](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 | [](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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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
--------------------------------------------------------------------------------