jede Woche eine Vorlesung, dort werden Hausaufgaben gestellt
Aufgaben zur Präsentation in der nächsten Übung
jeder soll (als Teil einer Gruppe) insgesamt 3 mal präsentieren
Aufgaben in autotool (selbständige Bearbeitung innerhalb der nächsten zwei Wochen)
jeder soll insgesamt 50 % der Pflichtaufgaben erledigen
Prüfung: Klausur am Computer (autotool, in Präsenz unter Aufsicht)
Skript (Woche für Woche)
Plan: vgl. How I Teach Functional Programming, WFLP 2017,
Quelltexte aus Vorlesung, Vorbereitung Hausaufgaben (zur Präsentation):
Einschreiben! (Projekt wird dann private geschaltet)
Hausaufgaben (individuell)
Einschreiben! (Übungsgruppe wählen, Hinweis beachten)
Arbeiten im Pool: Shell, $PATH
, ghci
,
vgl.
$ cabal update
# $HOME/.config/cabal/config editieren (-haddock)
$ cabal install --lib leancheck
$ ghci
GHCi, version 9.12.2: https://www.haskell.org/ghc/ :? for help
ghci> import Test.LeanCheck
ghci> check $ \ p q -> (p && q) == (q && p)
ghci> :doc check
ssh-keygen
, .ssh/id_ed25519.pub
\(\Rightarrow\) gitlab.dit
,
git clone
wenn Zeit ist: autotool 15-1,
1. Sem: Modellierung (formale Spezifikationen (von konkreten und abstrakten Datentypen))
1./2. Sem Grundlagen der (AO) Programmierung
imperatives Progr. (Programm ist Folge von Anweisungen, bewirkt Zustandsänderung)
strukturiertes P. (genau ein Eingang/Ausgang je Teilp.)
objektorientiertes P. (Interface \(=\) abstrakter Datentyp, Klasse \(=\) konkreter Datentyp)
2. Sem: Algorithmen und Datenstrukturen
(Spezifikation, Implementierung, Korrektheit, Komplexität)
3. Sem: Softwaretechnik (industrielle Softwareproduktion)
deklarative Programmierung
(Programm ist ausführbare Spezifikation)
insbesondere: funktionale Programmierung
Def: Programm berechnet Funktion \(f:\text{Eingabe}\mapsto\text{Ausgabe}\),
(kein Zustand, keine Zustandsänderungen)
Daten (erster Ordnung) sind Bäume
Programm ist Gleichungssystem
Programme sind auch Daten (höherer Ordnung)
ausdrucksstark, sicher, effizient, parallelisierbar
funktionale Programmierung: foldr (+) 0 [1,2,3]
foldr f z l = case l of
[] -> z ; (x:xs) -> f x (foldr f z xs)
logische Programmierung: append(A,B,[1,2,3]).
append([],YS,YS).
append([X|XS],YS,[X|ZS]):-append(XS,YS,ZS).
Constraint-Programmierung
(set-logic QF_LIA) (set-option :produce-models true)
(declare-fun a () Int) (declare-fun b () Int)
(assert (and (>= a 5) (<= b 30) (= (+ a b) 20)))
(check-sat) (get-value (a b))
Rechnen \(=\) Auswerten von Ausdrücken (Termbäumen)
Dabei wird ein Wert bestimmt
und es gibt keine (versteckte) Wirkung.
(engl.: side effect, dt.: Nebenwirkung)
Werte können sein:
“klassische” Daten (Zahlen, Listen, Bäume…)
True :: Bool
,
[3.5, 4.5] :: [Double]
Funktionen (Sinus, …)
[sin, cos] :: [Double -> Double]
Aktionen (Datei lesen, schreiben, …)
readFile "foo.text" :: IO String
…der funktionalen Programmierung
Beweisbarkeit: Rechnen mit Programmen
wie in der Mathematik mit Termen
Sicherheit: es gibt keine Nebenwirkungen
und Wirkungen sieht man bereits am Typ
Aussdrucksstärke, Wiederverwendbarkeit: durch Funktionen höherer
Ordnung (sog. Entwurfsmuster)
Effizienz: durch Programmtransformationen im Compiler,
Parallelität: keine Nebenwirkungen \(\Rightarrow\) keine data
races,
fktl. Programme sind automatisch parallelisierbar
import Test.LeanCheck
append :: forall t . [t] -> [t] -> [t]
append [] y = y
append (h : t) y = h : (append t y)
associative f =
\ x y z -> f x (f y z) == f (f x y) z
commutative f = \ x y -> ...
test = check (associative (append @Bool))
Übung: Kommutativität (formulieren und testen)
app :: forall t . [t] -> [t] -> [t]
app [] y = y
app (h : t) y = h : (app t y)
Lemma: app x (app y z) .=. app (app x y) z
Proof by induction on List x
Case []
To show: app [] (app y z) .=. app (app [] y) z
Case h:t
To show: app (h:t) (app y z) .=. app (app (h:t) y) z
IH: app t (app y z) .=. app (app t y) z
CYP https://github.com/noschinl/cyp,
ist vereinfachte Version
von Isabelle https://isabelle.in.tum.de/
-- Länge der Collatz-Folge
collatz :: Int -> Int
collatz x = if x <= 1 then 0
else 1 + collatz (if even x then div x 2 else 3*x+1)
-- Summe der Längen
main :: IO ()
main = print $ sum
$ map collatz [1 .. 10^7]
wird parallelisiert durch Strategie-Annotation:
import Control.Parallel.Strategies
...
main = print $ sum
$ withStrategy (parListChunk (10^5) rseq)
$ map collatz [1 .. 10^7]
Die Anzahl der 1-Bits einer nichtnegativen Zahl:
Func<int,int>f =
x=>{int s=0; while(x>0){s+=x%2;x/=2;}return s;}
\(\displaystyle\sum_{x=0}^{2^{26}-1} f(x)\)
Enumerable.Range(0,1<<26).Select(f).Sum()
automatische parallele Auswertung, Laufzeitvergleich:
Time(()=>Enumerable.Range(0,1<<26).Select(f).Sum())
Time(()=>Enumerable.Range(0,1<<26)
.AsParallel().WithDegreeOfParallelism(4)
.Select(f).Sum())
vgl. Introduction to PLINQ
…der statischen Typisierung
The language in which you write profoundly affects the design of programs written in that language.
For example, in the OO world, many people use UML to sketch a design. In Haskell or ML, one writes type signatures instead. Much of the initial design phase of a functional program consists of writing type definitions.
Unlike UML, though, all this design is incorporated in the final product, and is machine-checked throughout.
Simon Peyton Jones, in: Masterminds of Programing, 2009;
funktionale Programmierung: diese Vorlesung
logische Programmierung: in Grundl. Künstl. Intell.
Constraint-Programmierung: als Wahlfach (WS 23)
Beziehungen zu weiteren LV: Voraussetzungen
Bäume, Terme (Modellierung, Alg.+DS)
Logik (Grundlagen TI, Softwaretechnik)
Anwendungen:
Softwarepraktikum
weitere Sprachkonzepte in Prinzipien v. Programmiersprachen
Programmverifikation (vorw. f. imperative Programme)
Funktionale Programmierung ist ein Konzept. Realisierungen:
in prozeduralen Sprachen:
Unterprogramme als Argumente (in Pascal)
Funktionszeiger (in C)
in OO-Sprachen: Befehlsobjekte
Multi-Paradigmen-Sprachen:
Lambda-Ausdrücke in C#, Scala, Clojure
funktionale Programmiersprachen (LISP, ML, Haskell)
Die Erkenntnisse sind sprachunabhängig.
A good programmer can write LISP in any language.
Learn Haskell and become a better Java programmer.
Terme, Termersetzungssysteme, algebraische Datentypen, Pattern Matching, Persistenz
Funktionen (polymorph, höherer Ordnung), Lambda-Kalkül, Rekursionsmuster
Typklassen zur Steuerung der Polymorphie
(Anwendung: automatische Testdatenerzeugung)
Bedarfsauswertung, unendl. Datenstrukturen
Konstruktorklassen (Functor, Applicative, Monad)
Collections (endliche Mengen, Abbildungen, Folgen)
als Anwendung vorher gezeigter Konzepte
algebraische Datentypen, Pattern Matching, Termersetzungssysteme
Scale: case class, Java: Entwurfsmuster Kompositum,
immutable objects (record
), das Datenmodell von
Git
Funktionen (höherer Ordnung), Lambda-Kalkül, Rekursionsmuster
Lambda-Ausdrücke in C#, Entwurfsmuster Besucher
Codequalität, code smells, Refaktorisierung
Typklassen zur Steuerung der Polymorphie: Interfaces
Bedarfsauswertung, unendl. Datenstrukturen
Iteratoren, Ströme, LINQ
Functor, Applicative, Monad: map
,
flatMap
wissenschaftliche Quellen zur aktuellen Forschung und Anwendung der funktionalen Programmierung
Journal of Functional Programming (CUP) https://www.cambridge.org/core/journals/journal-of-functional-programming
Intl. Conference Functional Programming (ACM SIGPLAN) https://www.icfpconference.org/
Intl. Workshop Trends in Functional Programming in Education https://wiki.tfpie.science.ru.nl/
(Sprachstandard, Werkzeuge, Bibliotheken, Tutorials),
Skript aktuelles Semester https://www.imn.htwk-leipzig.de/~waldmann/lehre.html
How I Teach Functional Programming (WFLP 2017) https://www.imn.htwk-leipzig.de/~waldmann/talk/17/wflp/
Kriterium für Haskell-Tutorials und -Lehrbücher:
wo werden data
(benutzerdefinerte algebraische
Datentypen) und case
(pattern matching) erklärt?
Je später, desto schlechter!
Q: Aber in Wikipedia/Stackoverflow steht, daß …
A: Na und.
Es mag eine in Einzelfällen nützliche Übung sein,
sich mit dem Halbwissen von Nichtfachleuten auseinanderzusetzen.
(Aber
)
In VL und Übung verwenden und diskutieren wir die durch Dozenten/Skript/Modulbeschreibung vorgegebenen Quellen (Lehrbücher, referierte Original-Artikel, Standards zu Sprachen und Bibliotheken)
…gilt entsprechend für Ihre Bachelor- und Master-Arbeit.
Wikipedia: benutzen—ja (um Primärquellen zu finden), zitieren—nein (ist keine wissenschaftliche Quelle).
jede Woche eine Vorlesung, eine Übung
Hausaufgaben
gruppenweise: markierte Aufgaben aus dem Skript: anmelden (Wiki), diskutieren (Issue-Tracker), vorrechnen (in der jeweils nächsten Übung)
individuell (jeweils 2 Wochen Bearbeitungszeit) https://autotool.imn.htwk-leipzig.de/new/
Prüfungszulassung: regelmäßiges und erfolgreiches Bearbeiten der Übungsaufgaben.
Vorrechnen: 3 mal,
Autotool: 50 Prozent der Pflicht-Aufgaben,
Prüfung: Klausur 120 min (am Computer), keine Hilfsmittel
Informationen zur VL: https://www.imn.htwk-leipzig.de/~waldmann/lehre.html
digitale Selbstverteidigung: Browser und Suchmaschine datenschutzgerecht auswählen und einstellen.
Das Geschäftsmodell der Überwachungswirtschaft ist es, Ihren Bildschirmplatz, und damit Ihre Aufmerksamkeit und Ihre Lebenszeit an Anzeigenkunden zu verkaufen. Um dabei höhere Erlöse zu erzielen, wird Ihr Verhalten vermessen, gespeichert, vorhergesagt und beeinflußt. Die dazu angelegten Personenprofile erlauben eine umfassende privatwirtschaftliche und staatliche Überwachung. Diese soll verschleiert, verharmlost und legalisiert werden.
Siehe auch
OS Überwachungskapitalismus https://www.imn.htwk-leipzig.de/~waldmann/talk/19/ubkap/,
VL Informatik (Nebenfach) https://www.imn.htwk-leipzig.de/~waldmann/edu/ws21/inf/folien/#(11)
Benutzung Rechnerpool (ssh, tmux, ghci) https://www.imn.htwk-leipzig.de/~waldmann/etc/pool/
Beispiel Funktionale Programmierung
$ /usr/local/waldmann/opt/ghc/latest/bin/ghci
ghci> length $ takeWhile (== '0') $ reverse $ show $ foldr (*) 1 [1 .. 100 :: Integer]
Typ und Wert von Teilausdrücken feststellen, z.B.
ghci> :set +t
ghci> foldr (*) 1 [1..100 :: Integer]
Beachte polymorphe numerische Literale.
(Auflösung der Polymorphie durch Typ-Annotation.)
Warum ist 100 Fakultät als Int
gleich 0?
Welches ist der Typ der Funktion takeWhile
?
Beispiel:
odd 3 ==> True ; odd 4 ==> False
takeWhile odd [3,1,4,1,5,9] ==> [3,1]
ersetze in der Lösung takeWhile
durch andere
Funktionen des gleichen Typs (suche diese mit Hoogle), erkläre
Semantik
typische Eigenschaften dieses Beispiels (nachmachen!)
statische Typisierung, Schachtelung von Funktionsaufrufen, Funktion höherer Ordnung, Benutzung von Funktionen aus Standardbibliothek (anstatt selbstgeschriebener).
schlechte Eigenschaften (vermeiden!)
Benutzung von Zahlen und Listen (anstatt anwendungsspezifischer Datentypen) vgl. http://www.imn.htwk-leipzig.de/~waldmann/etc/untutorial/list-or-not-list/
Haskell-Entwicklungswerkzeuge
Compiler, REPL: ghci (Fehlermeldungen, Holes)
API-Suchmaschine
Editor: Emacs https://xkcd.com/378/,
IDE? gibt es, brauchen wir (in dieser VL) nicht https://hackage.haskell.org/package/haskell-language-server
Softwaretechnik im autotool:
benutzen Sie gitlab.imn zur Koordinierung: (einmalig) Einteilung in Dreiergruppen, (wöchentlich) Bearbeitung der Aufgaben. Benutzen Sie Wiki und Issues mit sinnvollen Titeln/Labeln. Schließen Sie erledigte Issues.
Jede der markierten Aufgabe kann in jeder Übung aufgerufen werden (Bsp: Aufg. 3 in den INB-Übungen und in der MIB-Übung) Es kann dann eine vorher gemeinsam (von mehreren Gruppen) vorbereitete Lösung präsentiert werden—die aber von jedem einzelnen Präsentator auch verstanden sein sollte.
Auch die nicht markierten Aufgaben können in den Übungen diskutiert werden—wenn dafür Zeit ist.
SS 25: Aufgabe 1, 4, 5
Digitale Selbstverteidigung
Welche Daten gibt Ihr Browser preis?
Starten Sie in einer Konsole den Befehl
nc -l -p 9999
(Konsole soll sichtbar bleiben)
Rufen Sie im Browser die Adresse http://localhost:9999
auf, beobachten Sie die Ausgabe in der Konsole.
Wie (personen)spezifisch ist diese Information?
Wie können weitere Informationen extrahiert werden? Verwenden Sie https://www.eff.org/press/releases/test-your-online-privacy-protection-effs-panopticlick (Electronic Frontier Foundation, 2015–)
Stellen Sie Firefox datenschutzgerecht ein. (Das beginnt mit der Default-Startseite!)
Zeigen Sie die Benutzung von temporary containers, von Profilen (z.B. ein Profil für Browsing im Screen-Share).
Führen Sie Browser-Plugins uMatrix
,
uBlockOrigin
vor.
zu: E. W. Dijkstra: Answers to Questions from Students of Software Engineering (Austin, 2000) (EWD 1035)
putting the cart before the horse
übersetzen Sie wörtlich ins Deutsche,
geben Sie eine entsprechende idiomatische Redewendung in Ihrer Muttersprache an,
wofür stehen cart und horse hier konkret?
sind die empfohlenen exakten Techniken der Programmierung für große Systeme anwendbar?
Erklären Sie lengths of …grow not much more than linear with the lengths of ….
Welche Längen werden hier verglichen?
Modellieren Sie das System als Graph, die Knoten sind die Komponenten, die Kanten sind deren Beziehungen (direkte Abhängigkeiten).
Welches asymptotische Wachstum ist bei undisziplinierter Entwicklung des Systems zu befürchten?
Welche Graph-Eigenschaft impliziert den linearen Zusammenhang?
Wie gestaltet man den System-Entwurf, so daß diese Eigenschaft tatsächlich gilt? Welchen Nutzen hat das für Entwicklung und Wartung?
Lesen Sie E. W. Dijkstra: On the foolishness of "natural language programming" https://www.cs.utexas.edu/users/EWD/transcriptions/EWD06xx/EWD667.html
und beantworten Sie
womit wird “einfaches Programmieren” fälschlicherweise gleichgesetzt?
welche wesentliche Verbesserung brachten höhere Programmiersprachen, welche Eigenschaft der Maschinensprachen haben sie trotzdem noch?
warum sollte eine Schnittstelle narrow sein?
welche formalen Notationen von Vieta, Descartes, Leibniz, Boole sind gemeint? (jeweils: Wissenschaftsbereich, (heutige) Bezeichnung der Notation, Beispiele)
warum können Schüler heute das lernen, wozu früher nur Genies in der Lage waren?
Übersetzen Sie den Satz “the naturalness of …obvious”.
Geben Sie dazu jeweils an:
die Meinung des Autors, belegt durch konkrete Textstelle und zunächst wörtliche, dann sinngemäße Übersetzung
Beispiele aus Ihrer Erfahrung
Über ein Monoid \((M,\circ, 1)\) mit Elementen \(a, b\in M\) (sowie eventuell weiteren) ist bekannt: \(a^2= b^2 = (ab)^2 = 1\).
Dabei ist \(ab\) eine Abkürzung für \(a\circ b\) und \(a^2\) für \(aa\), usw.
Geben Sie ein Modell mit \(1\neq a\neq b\neq 1\) an.
Überprüfen Sie \(ab = ba\) in Ihrem Modell.
Leiten Sie \(ab=ba\) aus den Monoid-Axiomen und gegebenen Gleichungen ab.
Das ist eine Übung zur Wiederholung der Konzepte abstrakter und konkreter Datentyp sowie Spezifikation.
im Rechnerpool live vorführen:
ein Terminal öffnen
ghci
starten (in der aktuellen Version), Fakultät
von 100 ausrechnen
Datei F.hs
mit Texteditor anlegen und öffnen,
Quelltext f = ...
(Ausdruck mit Wert 100!
)
schreiben, diese Datei in ghci
laden, f
auswerten
Dabei wg. Projektion an die Wand:
Schrift 1. groß genug und 2. schwarz auf weiß.
Vorher Bildschirm(hintergrund) aufräumen, so daß bei Projektion keine
personenbezogenen Daten sichtbar werden. Beispiel:
export PS1="$ "
ändert den Shell-Prompt (versteckt den
Benutzernamen).
Wer eigenen Rechner im Pool benutzt:
Aufgaben wie oben und
ssh
-Login auf einen Rechner des Pools
(damit wird die Ausrede GHC (usw.) geht auf meinem Rechner nicht hinfällig)
ssh
-Login oder remote-Desktop-Zugriff von
einem Rechner des Pools auf Ihren Rechner (damit das projiziert werden
kann, ohne den Beamer umzustöpseln)
(falls das alles zu umständlich ist, dann eben doch einen Pool-Rechner benutzen)
(Prädikatenlogik) Signatur \(\Sigma\) ist Menge von Funktionssymbolen mit Stelligkeiten
ein Term \(t\) in Signatur \(\Sigma\) ist
Funktionssymbol \(f\in\Sigma\)
der Stelligkeit \(k\)
mit Argumenten \((t_1,\ldots,t_k)\),
die selbst Terme sind.
\(\operatorname{Term}(\Sigma)=\) Menge der Terme über Signatur \(\Sigma\)
(Graphentheorie) ein Term ist ein
gerichteter, geordneter, markierter Baum
(Datenstrukturen)
Funktionssymbol \(=\) Konstruktor, Term \(=\) Baum
Signatur: \(\Sigma=\{ Z/0, S/1, f/2 \}\)
Elemente von \(\operatorname{Term}(\Sigma)\):
\(Z(), \quad S(S(Z())), \quad f(S(S(Z())), Z())\)
Abkürzung: das leere Argument-Tupel (die Klammern) nach nullstelligen Symbolen weglassen, \(f(S(S(Z)),Z)\)
Signatur: \(\Gamma=\{ E/0, A/1, B/1 \}\)
Elemente von \(\operatorname{Term}(\Gamma)\): …
Bezeichnung: für Signatur \(\Sigma\) und \(k\in\NN\):
\(\Sigma_k\) bezeichnet Menge der Symbole aus \(\Sigma\) mit Stelligkeit \(k\)
\(\Sigma_0=\{Z\},\Sigma_1=\{S\},\Sigma_2=\{f\},\)
\(\Gamma_0=\{E\},\Gamma_1=\dots, \Gamma_2=\dots\)
die Größe: ist Funktion \(|\cdot|:\operatorname{Term}(\Sigma)\to\NN\) mit
für \(f\in\Sigma_k\) gilt \(|f(t_1,\ldots,t_k)| = 1 + |t_1| + \ldots + |t_k|\)
die Größe eines Terms ist der Nachfolger der Summe der Größen seiner Kinder
Bsp: \(|S(S(Z()))|=1+|S(Z())|=1+1+|Z()| = 1+1+1\)
\(|f(S(S(Z())),Z()|=\dots\)
die Höhe: ist Funktion \(\operatorname{\textsf {height}}:\operatorname{Term}(\Sigma)\to\NN\):
für \(t=f(t_1,\ldots,t_k)\) gilt
wenn \(k=0\), dann \(\operatorname{\textsf {height}}(t)= 0\)
wenn \(k>0\), dann \(\operatorname{\textsf {height}}(t)=1 + \max(\operatorname{\textsf {height}}(t_1),\ldots,\operatorname{\textsf {height}}(t_k))\)
Satz: \(\forall t\in\operatorname{Term}(\{a/0,b/2\}): |t|\equiv 1 \pmod 2\) (die Größe ist ungerade)
Beweis durch Induktion über den Termaufbau:
IA (Induktions-Anfang): \(t=a()\)
Beweis für IA: \(|t|=|f()|=1\equiv 1\pmod 2\)
IS (I-Schritt): \(t=b(t_1,t_2)\)
zu zeigen ist: IB (I-Behauptung): \(|t|\equiv 1\pmod 2\)
dabei benutzen: IV (I-Voraussetzung) \(|t_1|\equiv|t_2|\equiv 1\pmod 2\)
Beweis für IS: \(|t|=|b(t_1,t_2)|=1+|t_1|+|t_2| \equiv 1 + 1 + 1 \equiv 1 \pmod 2\)
Bezeichnung: das heißt IV, und nicht I-Annahme, damit es nicht mit I-Anfang verwechselt wird
Beispiel: Deklaration des Typs
data Foo = Con {bar :: Int, baz :: String}
deriving Show
Bezeichnungen:
Foo
ist Typname
Con
ist Konstruktor
bar, baz
sind Komponenten-Namen des
Konstruktors
Int, String
sind Komponenten-Typen
Beispiel: Konstruktion eines Datums dieses Typs
Con { bar = 3, baz = "hal" } :: Foo
der Ausdruck (vor dem ::
) hat den Typ
Foo
Beispiel: Deklaration des Typs
data Foo = Con Int String
Bezeichnungen:
Foo
ist Typname
Con
ist zweistelliger Konstruktor
…mit anonymen Komponenten
Int
, String
sind
Komponenten-Typen
Beispiel: Konstruktion eines Datums dieses Typs
Con 3 "hal" :: Foo
auch ein Konstruktor mit benannten Komponenten kann positionell aufgerufen werden
Beispiel (selbst definiert)
data T = A { foo :: Bool }
| B { bar :: Ordering, baz :: Bool }
deriving Show
Bespiele (in Standardbibliothek (Prelude) vordefiniert)
data Bool = False | True
data Ordering = LT | EQ | GT
Konstruktion solcher Daten:
False :: Bool
A { foo = False } :: T ; A False :: T
B EQ True :: T
(bisher) einsortige Signatur
ist Abbildung von Funktionssymbol nach Stelligkeit
(neu) mehrsortige Signatur
Menge von Sortensymbolen \(S=\{S_1,\ldots\}\)
msS ist Abb. von Funktionssymbol nach Typ
Typ ist Element aus \(S^*\times S\)
Folge der Argument-Sorten, Resultat-Sorte
Bsp.: \(S=\{Z,B\}, \Sigma=\{0 \mapsto ([],Z), p \mapsto ([Z,Z],Z),\) \(e\mapsto ([Z,Z],B), a\mapsto([B,B],B)\}\).
\(\operatorname{Term}(\Sigma,B)\) (Terme dieser Signatur mit Sorte \(B\)): …
Konstruktoren mit benannten Komponenten
data Tree = Leaf {}
| Branch { left :: Tree , right :: Tree }
mit anonymen Komponenten
data Tree = Leaf | Branch Tree Tree
Objekte dieses Typs erzeugen, Bsp:
Leaf :: Tree; Branch (Branch Leaf Leaf) Leaf :: Tree
Bezeichnung
data Tree = ... | Node ...
ist falsch (irreführend), denn sowohl äußere Knoten (Leaf) als auch innere Knoten (Branch) sind Knoten (Node)
Ü: die data-Dekl. für \(S=\{Z,B\}\), \(\Sigma=\{0 \mapsto ([],Z),\) \(p \mapsto ([Z,Z],Z),\) \(e\mapsto ([Z,Z],B), a\mapsto([B,B],B)\}\).
mathematisches Modell: Term über Signatur
programmiersprachliche Bezeichnung: algebraischer Datentyp (die Konstruktoren bilden eine Algebra)
praktische Anwendungen:
Formel-Bäume (in Aussagen- und Prädikatenlogik)
Suchbäume (in VL Algorithmen und Datenstrukturen, in
java.util.TreeSet<E>
)
DOM (Document Object Model) https://www.w3.org/DOM/DOMTR
JSON (Javascript Object Notation) z.B. für AJAX https://www.ecma-international.org/publications/standards/Ecma-404.htm
Geben Sie die Signatur des Terms \(\sqrt{a\cdot a + b\cdot b}\) an.
Bestimmen Sie \(|\sqrt{a\cdot a + b\cdot b}|\), \(\operatorname{\textsf {height}}(\sqrt{a\cdot a + b\cdot b})\).
Geben Sie ein Element \(t \in \operatorname{Term}(\{ f/1, g/3, c/0 \})\) an mit \(|t|=5\) und \(\operatorname{\textsf {height}}(t)\le 2\).
die Menge \(\operatorname{Term}(\{ f/1,
g/3, c/0 \})\) wird realisiert durch den Datentyp
data T = F T | G T T T | C deriving Show
deklarieren Sie den Typ in ghci, erzeugen Sie o.g. Term \(t\) (durch Konstruktoraufrufe)
Holes (Löcher) in Ausdrücken als Hilfsmittel bei der Programmierung durch schrittweises Verfeinern
ghci> data T = A Bool | B T deriving Show
ghci> A _
<interactive>:2:3: error:
• Found hole: _ :: Bool
• In the first argument of ‘A’, namely ‘_’
In the expression: A _
In an equation for ‘it’: it = A _
• Relevant bindings include ...
Valid hole fits include ...
False :: Bool
True :: Bool
...
SS 25: Aufgaben 2, 3, 4.
autotool-Aufgabe 15-2
Allgemeine Hinweise zur Bearbeitung von Haskell-Lückentext-Aufgaben in autotool:
Schreiben Sie den angezeigten Quelltext (vollständig! ohne
zusätzliche Leerzeichen am Zeilenanfang!) in eine Datei mit Endung
.hs
, starten Sie ghci mit diesem Dateinamen als
Argument
ändern Sie den Quelltext: ersetzen Sie undefined
durch einen geeigneten Ausdruck, hier z.B.
solution = S.fromList [ False, G ]
im Editor speichern, in ghci neu laden (:r
)
reparieren Sie Typfehler, werten Sie geeignete Terme aus, hier
z.B. S.size solution
werten Sie test
aus, wenn test
den Wert
True ergibt, dann tragen Sie die Lösung in autotool ein.
Geben Sie einen Typ \(T\) (eine
data
-Deklaration) an, der alle Terme der einsortigen
Signatur \(\Sigma=\{E/0, F/2, G/3\}\)
enthält.
Konstruieren Sie Elemente dieses Typs.
Geben Sie \(t\in\operatorname{Term}(\Sigma)\) an mit
\(\operatorname{\textsf {height}}(t)=2\) und \(|t|\) möglichst klein
\(\operatorname{\textsf {height}}(t)=2\) und \(|t|\) möglichst groß
Allgemeine Hinweise zu Arbeit und Präsentation im Pool:
beachten Sie https://www.imn.htwk-leipzig.de/~waldmann/etc/pool/
(PATH
und ggf. LD_LIBRARY_PATH
)
Freigabe (für Dozenten-Rechner) mit krfb
,
Einmalpaßwort
Schrift schwarz auf weiß! Vernünftige Schriftgröße (Control-Plus)!! Gleichzeitig sichtbar (d. h.: keine Verdeckungen, Umschaltungen): Aufgabenstellung, Programmtext, Ausgabe/Fehlermeldungen. Wenn der Desktop-Hintergrund sichtbar ist—wurde Platz verschenkt!!!
Geben Sie einen Typ (eine data
-Deklaration) mit
genau 71 Elementen an. Sie können weitere Data-Deklarationen benutzen.
Minimieren Sie die Gesamt-Anzahl der Konstruktoren.
Bsp:
data Bool = False | True ; data T = X Bool Bool
dieses T
hat 4 Elemente, 3 Konstruktoren
(False,True,X
)
Beweisen Sie \(\forall \Sigma: \forall t\in\operatorname{Term}(\Sigma): \operatorname{\textsf {height}}(t) \le |t|-1\).
durch Induktion über den Term-Aufbau.
Induktions-Anfang: \(t=f()\) (nullstelliges Symbol \(f\))
Induktions-Schritt:
\(t=f(t_1,\dots,t_k)\) (\(k\)-stelliges Symbol \(f\), für \(k>0\))
dabei Induktions-Voraussetzung: die Behauptung gilt für \(t_1,\ldots,t_k\).
Induktions-Behauptung: …für \(t\).
Für welche Terme \(t\) gilt Gleichheit? Wo sieht man das im Beweis?
wieviele Elemente des Datentyps data T = L | B T T
haben …
die Größe 9
die Größe \(\le 9\)
die Höhe \(0, 1, 2, 3, \dots, k, \dots\)
Sie müssen diese Elemente nicht alle einzeln angeben.
Bestimmen sie ihre Anzahl durch dynamische Programmierung (von Hand).
Ersetzen Sie undefined
, so daß der Ausdruck
test
den Wert True hat.
module Blueprint where
import qualified Data.Set as S
-- aus Prelude importiert:
-- data Bool = False | True
data C = R | G | B deriving (Eq, Ord, Show)
data T = X C Bool | Y Bool | Z deriving (Eq, Ord, Show)
solution :: S.Set T
solution = S.fromList undefined
test :: Bool
test = S.size solution == 9
Ansatz einer Lösung:
solution = S.fromList [ X R False, Y True ]
einen Term in einer mehrsortigen Signatur angeben (Programmiersprache: Java)
Gesucht ist ein Ausdruck vom Typ int
in der Signatur
Foo e;
String g;
static char a ( Bar x, String y, String z );
static Bar b ( Foo x );
static int c ( int x, String y );
static int d ( char x, Foo y, String z );
static Foo f ( int x );
static String h ( Foo x, String y, char z );
Lösungsansatz
d (a (b (e), ...), ...)
Fill holes (_) (replace with one item)
and ellipsis (...) (replace with several items)
in the following, so that the claim at the top becomes true.
For this exercise, each data declaration can only refer to types defined earlier -
not to itself or later (it cannot be recursive).
size_of (T) == 71 where
{ data Bool = False | True
; data Col = R | G | B
; data S = ...
; data T = ...
}
wir haben: für Baum-artige Daten:
mathematisches Modell: Terme über einer Signatur
Realisierung als: algebraischer Datentyp
(data
)
wir wollen: für Programme, die diese Daten verarbeiten:
mathematisches Modell: Termersetzung
Realisierung als: Pattern matching (case
)
Position: Folge von natürlichen Zahlen
(bezeichnet einen Pfad von der Wurzel zu einem Knoten)
Beispiel: für \(t = S(f(S(S(Z())), Z()))\)
ist \([0,1]\) eine Position in \(t\).
\(\operatorname{Pos}(t) =\) die Menge der Positionen eines Terms \(t\)
Definition: wenn \(t=f(t_0,\ldots,t_{k-1})\), d.h., \(k\) Kinder
dann \(\operatorname{Pos}(t)= \{ [] \} \cup \{ [i] \cdot p \mid 0\le i< k \wedge p\in \operatorname{Pos}(t_i) \}\).
dabei bezeichnen:
\([]\) die leere Folge,
\([i]\) die Folge der Länge 1 mit Element \(i\),
\(\cdot\) den Verkettungsoperator für Folgen
\(t[p] =\) der Teilterm von \(t\) an Position \(p\)
Beispiel: \(S(f(S(S(Z())), Z()))[0,1] = \dots\)
Definition (durch Induktion über die Länge von \(p\)): …
\(t[p := s]\) : wie \(t\), aber mit Term \(s\) an Position \(p\)
Beispiel: \(S(f(S(S(Z())), Z()))[[0,1]:=S(Z)] = \dots\)
Definition (durch Induktion über die Länge von \(p\)): …
\(\operatorname{Term}(\Sigma,V)=\) Menge der Terme über Signatur \(\Sigma\) mit Variablen aus \(V\)
Beispiel: \(\Sigma=\{Z/0,S/1,f/2\}, V=\{y\}\), \(f(Z(),y)\in\operatorname{Term}(\Sigma,V)\).
Substitution \(\sigma\): partielle Abbildung \(V \to \operatorname{Term}(\Sigma)\)
Beispiel: \(\sigma_1 = \{(y,S(Z()))\}\)
eine Substitution auf einen Term anwenden: \(t \sigma\):
Intuition: wie \(t\), aber statt \(v\) immer \(\sigma(v)\)
Beispiel: \(f(Z(),y)\sigma_1 = f(Z(),S(Z()))\)
Definition durch Induktion über \(t\)
Daten \(=\) Terme (ohne Variablen)
Programm \(R\) \(=\) Menge von Regeln
Bsp: \(R=\{ (f(Z(),y),y), \; (f(S(x),y),S(f(x,y)))\}\)
Regel \(=\) Paar \((l,r)\) von Termen mit Variablen
Relation \(\to_R\) ist Menge aller Paare \((t,t')\) mit
es existiert \((l,r)\in R\)
es existiert Position \(p\) in \(t\)
es existiert Substitution \(\sigma:(\operatorname{Var}(l)\cup \operatorname{Var}(r))\to\operatorname{Term}(\Sigma)\)
so daß \(t[p] = l \sigma\) und \(t' = t[p := r \sigma]\).
\(\to_R\) beschreibt einen Schritt der Rechnung von \(R\),
transitive und reflexive Hülle \(\to_R^*\)
beschreibt Folge von Schritten.
Resultat einer Rechnung ist Term in \(R\)-Normalform
(\(:=\) ohne \(\to_R\)-Nachfolger)
dieses Berechnungsmodell ist im allgemeinen
nichtdeterministisch \(R_1=\{ C(x,y) \to x, C(x,y) \to y \}\)
(ein Term kann mehrere \(\to_R\)-Nachfolger haben,
ein Term kann mehrere Normalformen erreichen)
nicht terminierend \(R_2= \{ p(x,y) \to p(y,x) \}\)
(es gibt eine unendliche Folge von \(\to_R\)-Schritten,
es kann Terme ohne Normalform geben)
Für TRS \(R\) über Signatur \(\Sigma\): Symbol \(s\in\Sigma\) heißt
definiert, wenn \(\exists
(l,r)\in R : l[] = s(\dots)\)
(das Symbol in der Wurzel ist \(s\))
sonst Konstruktor.
Das TRS \(R\) heißt Konstruktor-TRS, falls:
definierte Symbole kommen links nur in den Wurzeln vor
Übung: diese Eigenschaft formal spezifizieren
Beispiele: \(R_1=\{a(b(x)) \to b(a(x))\}\) über \(\Sigma_1=\{a/1,b/1\}\),
\(R_2=\{f(f(x,y),z) \to f(x,f(y,z))\) über \(\Sigma_2=\{f/2\}\):
definierte Symbole? Konstruktoren? Konstruktor-System?
Funktionale Programme sind ähnlich zu Konstruktor-TRS.
Termersetzungssystem:
Signatur: \(\{(S,1),(Z,0),(f,2)\}\), Variablenmenge \(\{x',y\}\)
Ersetzungssystem \(\{ f(Z,y) \to y, f(S(x'),y) \to S(f(x',y)) \}\).
ist Konstruktor-System, definierte Symbole: \(\{f\}\), Konstruktoren: \(\{S,Z\}\),
Startterm \(f(S(S(Z)),S(Z))\).
funktionales Programm:
data N = Z | S N -- Signatur für Daten
f :: N -> N -> N -- Signatur für Funktion
f Z y = y ; f (S x') y = S (f x' y) -- Gleichungen
f (S (S Z)) (S Z) -- Benutzung der definierten Fkt.
für die Definition einer Funktion \(f\) mit diesem Typ
data N = Z | S N ; f :: N -> N -> N
(eben gesehen) mehrere Gleichungen
f Z y = y
f (S x') y = S (f x' y)
äquivalente Notation: eine Gleichung,
in der rechten Seite: Verzweigung (erkennbar an
case
)
mit zwei Zweigen (erkennbar an ->
)
f x y = case x of
{ Z -> y ; S x' -> S (f x' y) }
data N = Z | S N ; data Bool = False | True
positive :: N -> Bool
positive x = case x of { Z -> False ; S x' -> True }
Syntax:
case <Diskriminante> of
{ <Muster> -> <Ausdruck> ; ... }
<Muster>
enthält Konstruktoren und Variablen,
entspricht linker Seite einer Term-Ersetzungs-Regel,
<Ausdruck>
entspricht rechter Seite
statische Semantik (eines case-Ausdrucks mit Typ
T
)
jedes <Muster>
hat gleichen Typ wie
<Diskrim.>
,
jeder <Ausdruck>
hat den Typ
T
dynamische Semantik:
Def.: \(t\) paßt zum Muster \(l\): es existiert \(\sigma\) mit \(l\sigma=t\)
für das erste Muster, das zum Wert der Diskriminante paßt, wird \(r\sigma\) ausgewertet
ein case
-Ausdruck heißt
disjunkt, wenn die Muster nicht überlappen
(es gibt keinen Term, der zu mehr als 1 Muster paßt)
vollständig, wenn die Muster den gesamten Datentyp abdecken
(es gibt keinen Term, der zu keinem Muster paßt)
Bespiele (für data T = A | B T | F T T
)
nicht disjunkt:
case t of { F (B x) y -> .. ; F x (B y) -> .. }
nicht vollständig
case t of { F x y -> .. ; A -> .. }
data
und case
typisches Vorgehen beim Verarbeiten algebraischer Daten vom Typ
T
:
Für jeden Konstruktor des Datentyps
data T = C1 ...
| C2 ...
schreibe einen Zweig in der Fallunterscheidung
f x = case x of
{ C1 ... -> ...
; C2 ... -> ... }
Argumente der Konstruktoren sind Variablen \(\Rightarrow\) Case-Ausdruck ist disjunkt und vollständig.
Scala: case classes https://docs.scala-lang.org/tutorials/tour/case-classes.html
Java (ab JDK 21)
jshell --enable-preview # Version 21-ea
interface I {}
record A (int x) implements I {}
I o = new A(4)
switch (o) {
case A(var y) : System.out.println(y);
default : }
Nicht verwechseln mit regular expression matching zur String-Verarbeitung. Es geht um algebraische (d.h. baum-artige) Daten!
der Datentyp
import qualified Prelude
data Bool = False | True
deriving Prelude.Show
die Negation
not :: Bool -> Bool
not x = case x of { False -> _ ; True -> _ }
die Konjunktion (als Operator geschrieben)
(&&) :: Bool -> Bool -> Bool
x && y = case x of { False -> _ ; True -> _ }
die Syntax eines Namens bestimmt, ob er als Funktion oder Operator verwendet wird:
Name aus Buchstaben (Bsp.: not
,
plus
)
steht als Funktion vor den Argumenten
Name aus Sonderzeichen (Bsp.: &&
)
steht als Operator zw. erstem und zweitem Argument
zwischen Funktion und Operator umschalten:
in runden Klammern: Operator als Funktion
(&&)::Bool->Bool->Bool
,
(&&) False True
in Backticks: Funktion als Operator
3 `plus` 4
not x = case x of { False -> _; True -> _ }
Alternative Notation (links), Übersetzung (rechts)
not x = case x of
False -> _
True -> _
not x = case x of
{False -> _
;True -> _
}
Abseitsregel (offside rule): wenn das nächste (nicht leere)
Zeichen nach of
kein { ist, werden eingefügt:
{ nach of
;
nach Zeilenschaltung bei gleicher
Einrückung
} nach Zeilenschaltung bei höherer Einrückung
Für die Signatur \(\Sigma=\{f/1,g/3,c/0\}\):
geben Sie ein \(t\in\operatorname{Term}(\Sigma))\) an mit \(t[1]=c\).
Beweisen Sie \(\forall \Sigma: \forall t\in\operatorname{Term}(\Sigma): |t| = |\operatorname{Pos}(t)|\).
Für die Signatur \(\Sigma=\{Z/0, S/1, f/2\}\):
für welche Substitution \(\sigma\) gilt \(f(x,Z) \sigma = f(S(Z),Z)\)?
für dieses \(\sigma\): bestimmen Sie \(f(x,S(x)) \sigma\).
Dabei wurde angewendet:
Abkürzung für Anwendung von 0-stelligen Symbolen: anstatt \(Z()\) schreibe \(Z\). (Vorsicht: dann kann man Variablen nicht mehr von 0-stelligen Symbolen unterscheiden. Man muß dann immer die Signatur explizit angeben oder auf andere Weise vereinbaren, wie man Variablen erkennt, z.B. Buchstaben am Ende das Alphabetes (\(\dots,x,y,\dots\)) sind Variablen, das ist aber riskant)
Für die Deklarationen
-- data Bool = False | True (aus Prelude)
data T = F T | G T T T | C
entscheide/bestimme für jeden der folgenden Ausdrücke:
syntaktisch korrekt?
statisch korrekt?
Resultat (dynamische Semantik)
disjunkt? vollständig?
1. case False of { True -> C }
2. case False of { C -> True }
3. case False of { False -> F F }
4. case G (F C) C (F C) of { G x y z -> F z }
5. case F C of { F (F x) -> False }
6. case F C of { F x -> False ; True -> False }
7. case True of { False -> C ; True -> F C }
8. case True of { False -> C ; False -> F C }
9. case C of { G x y z -> False; F x -> False; C -> True }
Listen von Wahrheitswerten:
data List = Nil | Cons Bool List deriving Prelude.Show
and :: List -> Bool
and l = case l of ...
entsprechend or :: List -> Bool
(Wdhlg.) welche Signatur beschreibt binäre Bäume
(jeder Knoten hat 2 oder 0 Kinder, die Bäume sind; es gibt keine Schlüssel)
geben Sie die dazu äquivalente data
-Deklaration an:
data T = ...
implementieren Sie dafür die Funktionen
size :: T -> Prelude.Int
depth :: T -> Prelude.Int
benutze Prelude.+
(das ist Operator),
Prelude.min, Prelude.max
für Peano-Zahlen data N = Z | S N
implementieren Sie plus, mal, min, max
SS 25: KW 18: Aufgaben 1, 4, 7; KW 19: Aufgaben 5, 6, 8
Arithmetik auf Peano-Zahlen
Für \(R=\{ f(S(x),y) \to f(x, S(y)), f(Z,y) \to y\}\)
bestimme alle \(R\)-Normalformen von \(f(S(Z), S(Z))\).
für \(R_d = R\cup\{ d(x)\to f(x,x) \}\)
bestimme alle \(R_d\)-Normalformen von \(d(d(S(Z)))\).
Bestimme die Signatur \(\Sigma_d\) von \(R_d\).
Bestimme die Menge der Terme aus \(\operatorname{Term}(\Sigma_d)\), die \(R_d\)-Normalformen sind.
Welche Rechenoperationen simulieren die Regeln für \(f\), für \(d\)?
welche Terme haben große Normalformen?
Simulation von Wort-Ersetzung durch Term-Ersetzung.
Abkürzung für mehrfache Anwendung eines einstelligen Symbols: \(A(A(A(A(x)))) = A^4(x)\)
für \(\{ A(B(x)) \to B(A(x)) \}\)
über Signatur \(\{A/1, B/1, E/0\}\):
bestimme Normalform von \(A^k (B^k (E))\)
für \(k=1, 2, 3,\) allgemein.
für \(\{ A(B(x)) \to B(B(A(x))) \}\)
über Signatur \(\{A/1, B/1, E/0\}\):
bestimme Normalform von \(A^k (B (E))\)
für \(k=1, 2, 3,\) allgemein.
für die Signatur \(\{A/2, D/0\}\):
definiere Terme \(t_0=D, t_{i+1} = A(t_i, D)\).
Zeichne \(t_3\). Bestimme \(|t_i|,\operatorname{depth}(t_i)\) .
für \(S=\{ A(A(D,x),y)\to A(x,A(x,y)) \}\)
bestimme \(S\)-Normalform(en), soweit existieren, der Terme \(t_0, t_1, \dots, t_4\).
Geben Sie für \(t_2\) die ersten Ersetzungs-Schritte explizit an.
Normalform von \(t_i\) allgemein.
Für die Deklarationen
-- data Bool = False | True (aus Prelude)
data S = A Bool | B | C S S
entscheide/bestimme für jeden der folgenden Ausdrücke:
syntaktisch korrekt?
Resultat-Typ (statische Semantik)
Resultat-Wert (dynamische Semantik)
Menge der Muster ist: disjunkt? vollständig?
1. case False of { True -> B }
2. case False of { B -> True }
3. case C B B of { A x -> x }
4. case A True of { A x -> False }
5. case A True of { A x -> False ; True -> False }
6. case True of { False -> A ; True -> A False }
7. case True of { False -> B ; False -> A False }
8. case B of { C x y -> False; A x -> x; B -> True }
weitere Beispiele selbst herstellen und dann in der Übung die anderen Teilnehmer fragen.
für selbst definierte Wahrheitswerte: deklarieren, implementieren und testen Sie:
die zweistellige Antivalenz,
die Implikation,
die dreistellige Majoritätsfunktion.
import qualified Prelude
data Bool = False | True deriving Prelude.Show
not :: ...
xor :: ...
...
Definieren Sie die Majorität auf verschiedene Weisen
mit einer Gleichung (evtl. mit case
, evtl.
geschachtelt)
ohne case
(evtl. mehrere
Gleichungen)
mit einer Gleichung ohne Fallunterscheidung, mittels anderer (selbst definierter) Funktionen
für binäre Bäume ohne Schlüssel
data Tree = Leaf | Branch Tree Tree
deklarieren, implementieren und testen Sie ein einstelliges Prädikat über solchen Bäumen, das genau dann wahr ist, wenn das Argument eine ungerade Anzahl von Blättern enthält.
Diese Anzahl nicht ausrechnen, sondern direkt den Wahrheitswert!
in welchen Fällen zeigt der Compiler GHC(i) die Warnung overlapping patterns? https://downloads.haskell.org/ghc/latest/docs/users_guide/using-warnings.html#ghc-flag-Woverlapping-patterns
Desgl. incomplete patterns?
Definieren Sie formal. Vergleichen Sie mit Def. disjunkt und vollständig aus VL.
Geben Sie Beispiele an mit selbst gebauten
data
-Typen.
also nicht die Beispiele aus der Dokumentation - keine Maschinen- oder andere Zahlen (Int, Integer), keine polymorphen Container (Tupel, Listen).
Der Haskell-Standard enthält
data Ordering = LT | EQ | GT
Für diesen Typ gibt es eine Operation (<>)
,
Bsp.
ghci> LT <> GT -- Resultat ist LT
implementieren Sie diese Funktion (unter anderem Namen) durch
eine möglichst kurze Fallunterscheidung.
op x y = case x of ...
ist sie kommutativ? assoziativ?
besitzt die Operation ein linksneutrales Element? ein rechtsneutrales? eine Umkehr-Operation? (ist das Monoid eine Gruppe?)
Testen Sie die Übereinstimmung der Definitionen sowie das Vorliegen der Eigenschaften mit leancheck, Bsp.
ghci> import Test.LeanCheck
ghci> check $ \ (x :: Ordering) -> (x <> x) == x
wie heißt die hier getestete Eigenschaft?
(Nachtrag statische Semantik, TODO: das sollte auf eine separate Folie) Beantworten Sie durch den Haskell-Standard (Language Report):
warum ist der folgende Ausdruck statisch falsch?
-- data Bool = False | True (aus Prelude)
data S = A Bool | B | C S S -- wie oben
case C B (C (A True) B) of { C x (C y x) -> True }
Erläuterungen zur Fehlermeldung siehe https://errors.haskell.org/messages/GHC-10498/, aber Verweis auf Standard fehlt dort, selbst suchen unter https://haskell.org/documentation/.
Welcher Abschnitt erklärt Fallunterscheidung? Dort wird Grammatik-Variable pat verwendet. In welchem anderen Abschnitt stehen deren Regeln? Nach diesen Regeln steht ein Satz, darin ein Begriff (ein Adjektiv) für eine Eigenschaft, die das Muster im Beispiel eben nicht hat.
Für Term-Ersetzungs-Regeln ist es erlaubt, in der logischen Programmierung auch, in der funktionalen üblicherweise nicht, weil die Implementierung des pattern matching dann deutlich teurer wäre. Warum?
gesucht ist für das System
TRS { variables = [ x, y, z ]
, rules =
[ f ( f ( x, y ), z ) -> f ( x, f ( y, z ) )
, f ( x, f ( y, z ) ) -> f ( f ( x, y ), z )
] }
eine Folge von Schritten
von f ( a, f ( f ( b, f ( c, d ) ), e ) )
nach f ( f ( a, f ( b, c ) ), f ( d, e ) )
Lösungs-Ansatz:
( f ( a, f ( f ( b, f ( c, d ) ), e ) )
, [ Step { rule_number = 1 , position = [ ]
, substitution = listToFM
[ (x, a), (z, e), (y, f (b, f (c, d))) ]
} ] )
KW 15: Daten (Terme, algebraische Datentypen)
KW 17: Programme (TRS, Pattern matching)
KW 19: Beweise, Induktion (cyp)
KW 20: Funktionen als Daten (\(\lambda\) - dyn. Semantik)
KW 21: Polymorphie (\(\lambda\) - stat. Semantik)
KW 23: eingeschränkte Polymorphie (Typklassen, Schnittstellen)
KW 24: Rekursionmuster
KW 25: Strictness, Bedarfsauswertung
KW 26: Datenströme (Iteratoren)
KW 27: Mengen-Operationen
KW 28: Zusammenfassung, Ausblick