2
0
Fork 0
mirror of https://github.com/MartinThoma/LaTeX-examples.git synced 2025-04-25 06:18:05 +02:00

Fixpunktkombinatoren; Haskell-Beispiele

This commit is contained in:
Martin Thoma 2014-03-20 13:42:52 +01:00
parent e910561dfe
commit 0174aa0cc6
5 changed files with 129 additions and 6 deletions

View file

@ -209,6 +209,11 @@ sich das ganze sogar noch kürzer schreiben:
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=fibonacci-zip.hs]{haskell}{scripts/haskell/fibonacci-zip.hs} \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=fibonacci-zip.hs]{haskell}{scripts/haskell/fibonacci-zip.hs}
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=fibonacci-pattern-matching.hs]{haskell}{scripts/haskell/fibonacci-pattern-matching.hs} \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=fibonacci-pattern-matching.hs]{haskell}{scripts/haskell/fibonacci-pattern-matching.hs}
Die unendliche Liste alle Fibonacci-Zahlen, also der Fibonacci-\textit{Stream}\xindex{Stream}
wird wie folgt erzeugt:
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=fibonacci-stream.hs]{haskell}{scripts/haskell/fibonacci-stream.hs}
\subsection{Polynome}\xindex{Polynome}\xindex{zipWith}\xindex{foldr}\xindex{tail}% \subsection{Polynome}\xindex{Polynome}\xindex{zipWith}\xindex{foldr}\xindex{tail}%
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=polynome.hs]{haskell}{scripts/haskell/polynome.hs} \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=polynome.hs]{haskell}{scripts/haskell/polynome.hs}
@ -222,6 +227,10 @@ sich das ganze sogar noch kürzer schreiben:
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=lauflaengencodierung.hs]{haskell}{scripts/haskell/lauflaengencodierung.hs} \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=lauflaengencodierung.hs]{haskell}{scripts/haskell/lauflaengencodierung.hs}
\subsection{Intersections}\xindex{Intersections}%
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=Intersect.hs]{haskell}{scripts/haskell/Intersect.hs}
\subsection{Funktionen höherer Ordnung}\xindex{Folds}\xindex{foldl}\xindex{foldr}\label{bsp:foldl-und-foldr} \subsection{Funktionen höherer Ordnung}\xindex{Folds}\xindex{foldl}\xindex{foldr}\label{bsp:foldl-und-foldr}
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=folds.hs]{haskell}{scripts/haskell/folds.hs} \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=folds.hs]{haskell}{scripts/haskell/folds.hs}

View file

@ -46,12 +46,12 @@ Die Funktionsapplikation sei linksassoziativ. Es gilt also:
Der untypisierte $\lambda$-Kalkül ist Turing-Äquivalent. Der untypisierte $\lambda$-Kalkül ist Turing-Äquivalent.
\end{satz} \end{satz}
\section{Reduktionen}\index{Reduktionen|(} \section{Reduktionen}\index{Reduktion|(}
\begin{definition}[Redex]\xindex{Redex}% \begin{definition}[Redex]\xindex{Redex}%
Eine $\lambda$-Term der Form $(\lambda x. t_1) t_2$ heißt Redex. Eine $\lambda$-Term der Form $(\lambda x. t_1) t_2$ heißt Redex.
\end{definition} \end{definition}
\begin{definition}[$\alpha$-Äquivalenz] \begin{definition}[$\alpha$-Äquivalenz]\xindex{Reduktion!Alpha ($\alpha$)}\xindex{Äquivalenz!Alpha ($\alpha$)}%
Zwei Terme $T_1, T_2$ heißen $\alpha$-Äquivalent, wenn $T_1$ durch Zwei Terme $T_1, T_2$ heißen $\alpha$-Äquivalent, wenn $T_1$ durch
konsistente Umbenennung in $T_2$ überführt werden kann. konsistente Umbenennung in $T_2$ überführt werden kann.
@ -67,7 +67,7 @@ Die Funktionsapplikation sei linksassoziativ. Es gilt also:
\end{align*} \end{align*}
\end{beispiel} \end{beispiel}
\begin{definition}[$\beta$-Äquivalenz] \begin{definition}[$\beta$-Äquivalenz]\xindex{Reduktion!Beta ($\beta$)}\xindex{Äquivalenz!Beta ($\beta$)}%
Eine $\beta$-Reduktion ist die Funktionsanwendung auf einen Redex: Eine $\beta$-Reduktion ist die Funktionsanwendung auf einen Redex:
\[(\lambda x. t_1) t_2 \Rightarrow t_1 [x \mapsto t_2]\] \[(\lambda x. t_1) t_2 \Rightarrow t_1 [x \mapsto t_2]\]
\end{definition} \end{definition}
@ -79,7 +79,7 @@ Die Funktionsapplikation sei linksassoziativ. Es gilt also:
\end{defenum} \end{defenum}
\end{beispiel} \end{beispiel}
\begin{definition}[$\eta$-Äquivalenz] \begin{definition}[$\eta$-Äquivalenz]\xindex{Reduktion!Eta ($\eta$)}\xindex{Äquivalenz!Eta ($\eta$)}%
Zwei Terme $\lambda x. f~x$ und $f$ heißen $\eta$-Äquivalent, wenn Zwei Terme $\lambda x. f~x$ und $f$ heißen $\eta$-Äquivalent, wenn
$x$ nicht freie Variable von $f$ ist. $x$ nicht freie Variable von $f$ ist.
\end{definition} \end{definition}
@ -87,7 +87,7 @@ Die Funktionsapplikation sei linksassoziativ. Es gilt also:
\begin{beispiel}[$\eta$-Äquivalenz] \begin{beispiel}[$\eta$-Äquivalenz]
TODO TODO
\end{beispiel} \end{beispiel}
\index{Reduktionen|)} \index{Reduktion|)}
\section{Auswertungsstrategien} \section{Auswertungsstrategien}
\begin{definition}[Normalenreihenfolge]\xindex{Normalenreihenfolge}% \begin{definition}[Normalenreihenfolge]\xindex{Normalenreihenfolge}%
@ -193,4 +193,101 @@ Auch die gewohnten Operationen lassen sich so darstellen.
\section{Weiteres} \section{Weiteres}
\begin{satz}[Satz von Curch-Rosser] \begin{satz}[Satz von Curch-Rosser]
Wenn zwei unterschiedliche Terme $a$ und $b$ äquivalent sind, d.h. mit Reduktionsschritten beliebiger Richtung ineinander transformiert werden können, dann gibt es einen weiteren Term $c$, zu dem sowohl $a$ als auch $b$ reduziert werden können. Wenn zwei unterschiedliche Terme $a$ und $b$ äquivalent sind, d.h. mit Reduktionsschritten beliebiger Richtung ineinander transformiert werden können, dann gibt es einen weiteren Term $c$, zu dem sowohl $a$ als auch $b$ reduziert werden können.
\end{satz} \end{satz}
\section{Fixpunktkombinator}
\begin{definition}[Fixpunkt]\xindex{Fixpunkt}%
Sei $f: X \rightarrow Y$ eine Funktion mit $\emptyset \neq A = X \cap Y$ und
$a \in A$.
$a$ heißt \textbf{Fixpunkt} der Funktion $f$, wenn $f(a) = a$ gilt.
\end{definition}
\begin{beispiel}[Fixpunkt]
\begin{bspenum}
\item $f_1: \mdr \rightarrow \mdr; f(x) = x^2 \Rightarrow x_1 = 0$ ist
Fixpunkt von $f$, da $f(0) = 0$. $x_2 = 1$ ist der einzige weitere
Fixpunkt dieser Funktion.
\item $f_2: \mdn \rightarrow \mdn$ hat ganz $\mdn$ als Fixpunkte, also
insbesondere unendlich viele Fixpunkte.
\item $f_3: \mdr \rightarrow \mdr; f(x) = x+1$ hat keinen einzigen Fixpunkt.
\item $f_4: \mdr[X] \rightarrow \mdr[X]; f(p) = p^2$ hat $p_1(x) = 0$ und
$p_2(x)=1$ als Fixpunkte.
\end{bspenum}
\end{beispiel}
\begin{definition}[Kombinator]\xindex{Kombinator}%
Ein Kombinator ist eine Abbildung ohne freie Variablen.
\end{definition}
\begin{beispiel}[Kombinatoren\footnotemark]%
\begin{bspenum}
\item $\lambda a.\ a$
\item $\lambda a.\ \lambda b.\ a$
\item $\lambda f.\ \lambda a.\ \lambda b. f\ b\ a$
\end{bspenum}
\end{beispiel}
\footnotetext{Quelle: \url{http://www.haskell.org/haskellwiki/Combinator}}
\begin{definition}[Fixpunkt-Kombinator]\xindex{Fixpunkt-Kombinator}%
Sei $f$ ein Kombinator, der $f\ g = g\ (f\ g)$ erfüllt. Dann heißt $f$
\textbf{Fixpunktkombinator}.
\end{definition}
Insbesondere ist also $f \ g$ ein Fixpunkt von $g$.
\begin{definition}[Y-Kombinator]\xindex{Y-Kombinator}%
Der Fixpunktkombinator
\[Y := \lambda f.\ (\lambda x.\ f\ (x\ x))\ (\lambda x.\ f\ (x\ x))\]
heißt $Y$-Kombinator.
\end{definition}
\begin{behauptung}
Der $Y$-Kombinator ist ein Fixpunktkombinator.
\end{behauptung}
\begin{beweis}\footnote{Quelle: Vorlesung WS 2013/2014, Folie 175}\leavevmode
\textbf{Teil 1:} Offensichtlich ist $Y$ ein Kombinator.
\textbf{Teil 2:} z.~Z.: $Y f \Rightarrow^* f \ (Y \ f)$
\begin{align*}
Y\ f &=\hphantom{^\beta f\ } (\lambda f.\ (\lambda x.\ f\ (x\ x))\ (\lambda x.\ f\ (x\ x)))\ f\\
&\Rightarrow^\beta\hphantom{f \ (\lambda f.\ } (\lambda x. f\ (x\ x))\ (\lambda x.\ f\ (x\ x))\\
&\Rightarrow^\beta f \ (\hphantom{\lambda f.\ }(\lambda x.\ f\ (x\ x))\ (\lambda x.\ f\ (x\ x)))\\
&\Rightarrow^\beta f \ (\lambda f.\ (\lambda x.\ f\ (x\ x))\ (\lambda x.\ f\ (x\ x))\ f)\\
&=\hphantom{^\beta} f \ (Y \ f)
\end{align*}
$\qed$
\end{beweis}
\begin{definition}[Turingkombinator]\xindex{Turingkombinator}%
Der Fixpunktkombinator
\[\Theta := (\lambda x. \lambda y. y\ (x\ x\ y)) (\lambda x.\ \lambda y.\ y\ (x\ x\ y))\]
heißt \textbf{Turingkombinator}.
\end{definition}
\begin{behauptung}
Der Turing-Kombinator $\Theta$ ist ein Fixpunktkombinator.
\end{behauptung}
\begin{beweis}\footnote{Quelle: Übungsblatt 6, WS 2013/2014}
\textbf{Teil 1:} Offensichtlich ist $\Theta$ ein Kombinator.
\textbf{Teil 2:} z.~Z.: $\Theta f \Rightarrow^* f \ (\Theta \ f)$
Sei $\Theta_0 := (\lambda x.\ \lambda y.\ y\ (x\ x\ y))$. Dann gilt:
\begin{align*}
\Theta\ f &= ((\lambda x.\ \lambda y.\ y\ (x\ x\ y))\ \Theta_0)\ f\\
&\Rightarrow^\beta (\lambda y. y\ (\Theta_0 \ \Theta_0 \ y))\ f\\
&\Rightarrow^\beta f \ (\Theta_0 \Theta_0 f)\\
&= f \ (\Theta \ f)
\end{align*}
$\qed$
\end{beweis}
Für den Turing-Operator gilt

View file

@ -0,0 +1,15 @@
module Intersect where
intersect :: (Ord t) => [t] -> [t] -> [t]
intersect a [] = []
intersect [] a = []
intersect (x:xs) (y:ys)
| x == y = x : intersect xs ys
| x < y = intersect xs (y:ys)
| y > y = intersect (x:xs) ys
intersectAll :: (Ord t) => [[t]] -> [t]
intersectAll (l:ls) = (foldr intersect l) ls
intersectAll [] = undefined
multiples n = [n*k | k <- [1..]]
commonMultiples a b c = intersectAll [ multiples n | n <- [a,b,c]]

View file

@ -0,0 +1,2 @@
fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)