├── .gitignore ├── .gitmodules ├── README.md ├── brainfuck.hs ├── effektsysteme.hs ├── effektsysteme.pdf ├── effektsysteme.tex ├── fixpunkt.gnuplot ├── fixpunkt.pdf ├── fixup-minted.pl ├── folien.pdf ├── folien.tex ├── fractran.hs ├── freie-monaden.hs ├── freie-monaden.pdf ├── freie-monaden.tex ├── freie-monaden.txt ├── images ├── a-monad-is-just-1.jpeg ├── a-monad-is-just-2.png ├── a-monad-is-just-3.jpeg ├── a-monad-is-just-4.jpeg ├── a-monad-is-just-5.jpeg ├── baum.fig ├── baum.pspdftex ├── baum_pspdftex.eps ├── baum_pspdftex.pdf ├── bird.png ├── book-knuth.png ├── book-onag.jpeg ├── book-onag.png ├── book-winning-ways.jpeg ├── bridge.jpeg ├── bug.png ├── cloud.png ├── committee.png ├── comonads-cofun.jpeg ├── cryptol.png ├── darcs.png ├── dedekind-titleslide.png ├── dedekind-toc.png ├── definition-free-monad.hs ├── do-stuff.jpeg ├── effects.png ├── endo.png ├── example-free-monad.hs ├── forest.jpeg ├── gargoyle.png ├── haskell-logo.png ├── haskell-spock.png ├── hilbert.jpeg ├── initial-algebras.hs ├── io.jpg ├── jabberwocky.jpg ├── kan-extension.jpeg ├── kasse.jpg ├── katze.jpg ├── lambdaschnecke.fig ├── lambdaschnecke.pdf ├── lambdaschnecke.pdf_t ├── lazy.jpg ├── learn-you-a-haskell-for-great-good.png ├── lock.jpg ├── logicomix-1.jpeg ├── logicomix-2.jpeg ├── luga.png ├── monadic-parser-combinators.jpeg ├── natural-transformation-law.hs ├── natural-transformation.hs ├── ordinal-numbers.png ├── paradox.jpeg ├── paths.pspdftex ├── paths_pspdftex.pdf ├── philosophen.png ├── philosophiae-newton.jpeg ├── present.png ├── principia-mathematica-1plus1.png ├── principia-mathematica.jpeg ├── pruefung.jpg ├── regex.png ├── run-coproduct.hs ├── rwh.jpg ├── sad-cat.jpg ├── sort.jpg ├── space.jpeg ├── stammbaum-der-surrealen-zahlen.png ├── standard.jpg ├── statef-functor.hs ├── stm.jpg ├── surreal1.png ├── surreal2.png ├── surreal3.png ├── surreal4.png ├── tablette.png ├── terminal-coalgebras.hs ├── thankyou.png ├── torus.png ├── types.jpg ├── typsystem.png ├── universal-property-free-monoid.hs ├── variable.jpg ├── where-no-man-has-gone-before.jpeg ├── wtf.jpg └── xmonad.png ├── impossible-maximum.hs ├── impossible-programs.lhs ├── initiale-algebren.pdf ├── initiale-algebren.tex ├── lightning-talk-tuebix2015.pdf ├── lightning-talk-tuebix2015.tex ├── lightning-talk.pdf ├── lightning-talk.tex ├── live-coding-ideen.txt ├── mandelbrot.b ├── monadic-parsing-snapshot-der-live-version.hs ├── monadic-parsing.hs ├── monadic-parsing.pdf ├── monadic-parsing.tex ├── surreal.hs ├── surreal.pdf ├── surreal.tex ├── typtheorie.pdf └── typtheorie.tex /.gitignore: -------------------------------------------------------------------------------- 1 | *.aux 2 | *.log 3 | *.nav 4 | *.out 5 | *.snm 6 | *.toc 7 | *.vrb 8 | *.hi 9 | *.o 10 | brainfuck 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "minted"] 2 | path = minted 3 | url = https://github.com/gpoore/minted.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | An introductory talk about Haskell (in German) 2 | ============================================== 3 | 4 | Was ist schneller als C++, prägnanter als Perl, regelmäßiger als Python, 5 | flexibler als Ruby, typisierter als C#, robuster als Java und hat 6 | absolut nichts mit PHP gemeinsam? Es ist Haskell! 7 | 8 | Haskell ist eine moderne und innovative Programmiersprache, die sich von 9 | bekannten imperativen Sprachen in vielerlei Hinsicht deutlich 10 | unterscheidet: Ein Haskell-Programm besteht nicht etwa aus einer Abfolge 11 | von auszuführenden Anweisungen, sondern aus einer Ansammlung von 12 | Deklarationen, deren Reihenfolge keine Rolle spielt. Auch gibt es keine 13 | veränderlichen Variablen, und ausgewertet wird nur, was wirklich 14 | benötigt wird; unendliche Datenstrukturen sind möglich und sinnvoll. 15 | 16 | Dieses Denkparadigma mag anfangs sehr ungewohnt sein, zieht jedoch eine 17 | Reihe von Vorteilen mit sich: Da es keine Nebenwirkungen wie 18 | beispielsweise globale Variablen gibt, kann man Code rein lokal 19 | verstehen. Damit wird es einfacher, modular Komponenten zusammenzubauen, 20 | sich Datenflüsse klarzumachen und Code auf seine Korrektheit hin zu 21 | überprüfen. Insbesondere vereinfacht sich die Programmierung mit Threads 22 | enorm. 23 | 24 | Ferner ist Haskells starkes statisches Typsystem eine große Hilfe beim 25 | Programmieren und verhindert viel mehr Fehler schon während des Kompilierens, 26 | als man vielleicht aus anderen Sprachen gewohnt ist. Es gibt das Motto, dass, 27 | wenn Haskell-Code erst einmal erfolgreich durchkompiliert, er dann auch schon 28 | korrekt ist. Das ist sicherlich übertrieben, hat aber einen erstaunlich wahren 29 | Kern. 30 | 31 | Der Vortrag wird einen subjektiven Überblick über die Fähigkeiten und 32 | typischen Anwendungsgebiete von Haskell geben. Beim Erlernen von Haskell 33 | lernt man viele neue Herangehensweisen kennen, die auch in anderen 34 | Sprachen nützlich sind; das ist einer der Hauptvorteile an Haskell, der 35 | auch dann noch relevant ist, wenn man aus verschiedenen Gründen nicht in 36 | Haskell programmieren möchte. 37 | -------------------------------------------------------------------------------- /brainfuck.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Control.Monad 4 | import Control.Monad.State 5 | import qualified Data.Map as M 6 | import Data.Char 7 | import Text.ParserCombinators.Parsec 8 | import System.IO 9 | 10 | data Stmt 11 | = IncPtr | DecPtr | IncVal | DecVal 12 | | PutChar | GetChar | While [Stmt] 13 | | Nop 14 | deriving (Show,Eq) 15 | 16 | data St = MkSt 17 | { ptr :: Int 18 | , mem :: M.Map Int Int 19 | } 20 | deriving (Show,Eq) 21 | 22 | type EvalM = StateT St IO 23 | 24 | initialSt :: St 25 | initialSt = MkSt 26 | { ptr = 0 27 | , mem = M.empty 28 | } 29 | 30 | eval :: Stmt -> EvalM () 31 | eval IncPtr = modify $ \st -> st { ptr = ptr st + 1 } 32 | eval DecPtr = modify $ \st -> st { ptr = ptr st - 1 } 33 | eval IncVal = modify $ \st -> st { mem = M.insert (ptr st) (look 0 (ptr st) (mem st) + 1) (mem st) } 34 | eval DecVal = modify $ \st -> st { mem = M.insert (ptr st) (look 0 (ptr st) (mem st) - 1) (mem st) } 35 | eval PutChar = do 36 | st <- get 37 | lift $ putChar $ chr $ look 0 (ptr st) (mem st) 38 | eval GetChar = do 39 | x <- lift getChar 40 | modify $ \st -> st { mem = M.insert (ptr st) (ord x) (mem st) } 41 | eval (While ss) = do 42 | st <- get 43 | if look 0 (ptr st) (mem st) /= 0 44 | then mapM_ eval ss >> eval (While ss) 45 | else return () 46 | eval Nop = return () 47 | 48 | look :: (Ord a) => b -> a -> M.Map a b -> b 49 | look def x v 50 | | Just y <- M.lookup x v = y 51 | | otherwise = def 52 | 53 | parseBrainfuck :: String -> Either ParseError [Stmt] 54 | parseBrainfuck input = parse (many parseStmt) "(unknown)" input 55 | 56 | run :: String -> IO () 57 | run input = do 58 | case parseBrainfuck input of 59 | Right ss -> evalStateT (mapM_ eval ss) initialSt 60 | Left e -> putStrLn . show $ e 61 | 62 | main :: IO () 63 | main = hSetBuffering stdout NoBuffering >> getContents >>= run 64 | 65 | parseStmt :: GenParser Char st Stmt 66 | parseStmt = choice [parseSimpleStmt, parseWhileStmt, parseDummy] 67 | 68 | parseSimpleStmt :: GenParser Char st Stmt 69 | parseSimpleStmt = do 70 | symbol <- oneOf "><+-.," 71 | case symbol of 72 | '>' -> return IncPtr 73 | '<' -> return DecPtr 74 | '+' -> return IncVal 75 | '-' -> return DecVal 76 | '.' -> return PutChar 77 | ',' -> return GetChar 78 | 79 | parseWhileStmt :: GenParser Char st Stmt 80 | parseWhileStmt = do 81 | char '[' 82 | body <- many parseStmt 83 | char ']' 84 | return $ While body 85 | 86 | parseDummy :: GenParser Char st Stmt 87 | parseDummy = do 88 | noneOf "><+-.,[]" 89 | return Nop 90 | 91 | helloWorldBF :: String 92 | helloWorldBF = 93 | "++++++++++\ 94 | \[\ 95 | \ >+++++++>++++++++++>+++>+<<<<-\ 96 | \] Schleife zur Vorbereitung der Textausgabe\ 97 | \>++. Ausgabe von 'H'\ 98 | \>+. Ausgabe von 'e'\ 99 | \+++++++. 'l'\ 100 | \. 'l'\ 101 | \+++. 'o'\ 102 | \>++. Leerzeichen\ 103 | \<<+++++++++++++++. 'W'\ 104 | \>. 'o'\ 105 | \+++. 'r'\ 106 | \------. 'l'\ 107 | \--------. 'd'\ 108 | \>+. '!'\ 109 | \>. Zeilenvorschub\ 110 | \+++. Wagenrücklauf" 111 | -------------------------------------------------------------------------------- /effektsysteme.hs: -------------------------------------------------------------------------------- 1 | {-# LANUGAGE ExistentialQuantification, KindSignatures, GADTs, Rank2Types #-} 2 | module Main where 3 | 4 | import Control.Monad.Error hiding (lift) 5 | import Data.IORef 6 | import System.Exit 7 | 8 | -------------------------------------------------------------------------------- 9 | -- Freie Monaden über freien Funktoren über Termkonstruktoren 10 | 11 | data Prog t a = 12 | Pure a | forall r. Step (t r) (r -> Prog t a) 13 | 14 | lift :: t a -> Prog t a 15 | lift x = Step x Pure 16 | 17 | instance Functor (Prog t) where 18 | fmap f (Pure x) = Pure (f x) 19 | fmap f (Step u k) = Step u (fmap f . k) 20 | 21 | instance Monad (Prog t) where 22 | return = Pure 23 | 24 | Pure x >>= f = f x 25 | Step u k >>= f = Step u ((>>= f) . k) 26 | 27 | 28 | -------------------------------------------------------------------------------- 29 | -- Beispiel: Die State-Monade spezifiert über die Signatur ihrer möglichen 30 | -- Nebenwirkungen und eine operationelle Semantik 31 | 32 | data StateI :: * -> * -> * where 33 | Get :: StateI s s 34 | Put :: s -> StateI s () 35 | 36 | type State s = Prog (StateI s) 37 | 38 | get :: State s s 39 | get = lift Get 40 | 41 | put :: s -> State s () 42 | put st = lift (Put st) 43 | 44 | runState :: State s a -> s -> (a,s) 45 | runState (Pure x) st = (x,st) 46 | runState (Step Get k) st = runState (k st) st 47 | runState (Step (Put st') k) st = runState (k ()) st' 48 | 49 | evalState :: State s a -> s -> a 50 | evalState = ((.) . (.)) fst runState 51 | 52 | 53 | -------------------------------------------------------------------------------- 54 | -- Beispiel: Einfaches Multitasking (über einer Basismonade) 55 | 56 | data ProcessI :: (* -> *) -> * -> * where 57 | Lift :: m a -> ProcessI m a 58 | Stop :: ProcessI m a 59 | Fork :: ProcessI m Bool 60 | Yield :: ProcessI m () 61 | 62 | liftBase :: m a -> Prog (ProcessI m) a 63 | liftBase = lift . Lift 64 | 65 | -- Interpreter, der nach jeder Aktion in der Basismonade die Kontrolle 66 | -- an den nächsten Prozess weitergibt 67 | runProcessForced :: (Monad m) => Prog (ProcessI m) a -> m () 68 | runProcessForced = schedule . (:[]) 69 | where 70 | schedule [] = return () 71 | schedule (m:ms) 72 | | Pure x <- m = schedule ms 73 | | Step (Lift u) k <- m = u >>= \x -> schedule (ms ++ [k x]) 74 | | Step Stop k <- m = schedule ms 75 | | Step Fork k <- m = schedule $ ms ++ [k True, k False] 76 | | Step Yield k <- m = schedule $ ms ++ [k ()] 77 | 78 | -- Interpreter, der nur bei Verwendung von Yield die Kontrolle an den 79 | -- nächsten Prozess übergibt 80 | runProcessCooperative :: (Monad m) => Prog (ProcessI m) a -> m () 81 | runProcessCooperative = schedule . (:[]) 82 | where 83 | schedule [] = return () 84 | schedule (m:ms) 85 | | Pure x <- m = schedule ms 86 | | Step (Lift u) k <- m = u >>= \x -> schedule (k x : ms) 87 | | Step Stop k <- m = schedule ms 88 | | Step Fork k <- m = schedule $ [k False] ++ ms ++ [k True] 89 | | Step Yield k <- m = schedule $ ms ++ [k ()] 90 | 91 | exProcess :: Prog (ProcessI IO) () 92 | exProcess = do 93 | liftBase $ putStrLn "Beginn." 94 | inChild <- lift Fork 95 | let debug msg = liftBase $ putStrLn $ (if inChild then "[K]" else "[E]") ++ " " ++ msg 96 | if inChild 97 | then do 98 | debug "Im Kindprozess." 99 | forM_ [1..5] $ \n -> do 100 | when (even n) $ lift Yield 101 | debug $ show n 102 | debug "Fertig im Kind." 103 | lift Stop 104 | else do 105 | debug "Im Elternprozess." 106 | forM_ [10..15] $ \n -> do 107 | when (even n) $ lift Yield 108 | debug $ show n 109 | debug "Fertig im Elternprozess." 110 | debug "Ganz fertig (nur der Elternprozess sollte hierhin gelangen)." 111 | 112 | 113 | -------------------------------------------------------------------------------- 114 | -- Koprodukt von Monaden 115 | 116 | data Sum m n a = Inl (m a) | Inr (n a) 117 | type Coprod m n = Prog (Sum m n) 118 | 119 | inl :: m a -> Coprod m n a 120 | inl x = Step (Inl x) Pure 121 | 122 | inr :: n a -> Coprod m n a 123 | inr x = Step (Inr x) Pure 124 | 125 | elim 126 | :: (Monad m, Monad n, Monad s) 127 | => (forall a. m a -> s a) 128 | -> (forall a. n a -> s a) 129 | -> (forall a. Coprod m n a -> s a) 130 | elim phi psi (Pure x) = return x 131 | elim phi psi (Step (Inl m) k) = phi m >>= elim phi psi . k 132 | elim phi psi (Step (Inr n) k) = psi n >>= elim phi psi . k 133 | 134 | 135 | -------------------------------------------------------------------------------- 136 | -- Beispiel: Koprodukt aus State- und Error-Monade 137 | 138 | type Err e = Either e 139 | type M = Coprod (State Int) (Err String) 140 | 141 | exM :: M Int 142 | exM = do 143 | st <- inl get 144 | if st <= 0 then inr (Left "Fehler") else do 145 | inl $ put (st - 1) 146 | return $ st^2 + st + 1 147 | 148 | runM :: Int -> M a -> IO a 149 | runM st m = newIORef st >>= \ref -> elim (embedState ref) embedErr m 150 | 151 | embedState :: IORef s -> State s a -> IO a 152 | embedState ref m = do 153 | st <- readIORef ref 154 | let (x,st') = runState m st 155 | writeIORef ref st' 156 | return x 157 | 158 | embedErr :: (Show e) => Err e a -> IO a 159 | embedErr (Left e) = putStrLn ("Fehler: " ++ show e) >> exitFailure 160 | embedErr (Right x) = return x 161 | -------------------------------------------------------------------------------- /effektsysteme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/effektsysteme.pdf -------------------------------------------------------------------------------- /effektsysteme.tex: -------------------------------------------------------------------------------- 1 | % Kompilieren mit: TEXINPUTS=minted/source: pdflatex -shell-escape % 2 | \documentclass[12pt,compress,ngerman,utf8,t]{beamer} 3 | \usepackage[ngerman]{babel} 4 | \usepackage{ragged2e} 5 | \usepackage{comment} 6 | \usepackage{minted} 7 | \usepackage{wasysym} 8 | \usepackage{tikz} 9 | \usetikzlibrary{calc} 10 | \usepackage[all]{xy} 11 | \usepackage[protrusion=true,expansion=false]{microtype} 12 | 13 | \title[Effektsysteme]{\smiley{} Effektsysteme \smiley} 14 | \author[Augsburger Curry Club]{ 15 | Ingo Blechschmidt \\[0.1em] \scriptsize\texttt{}} 16 | \date[2015-11-05]{\vspace*{-1.5em}\scriptsize Augsburger Curry-Club \\ 5. 17 | November 2015} 18 | 19 | \usetheme{Warsaw} 20 | 21 | \useinnertheme{rectangles} 22 | 23 | \usecolortheme{seahorse} 24 | \definecolor{mypurple}{RGB}{150,0,255} 25 | \setbeamercolor{structure}{fg=mypurple} 26 | 27 | \usefonttheme{serif} 28 | \usepackage[T1]{fontenc} 29 | \usepackage{libertine} 30 | 31 | \definecolor{darkred}{RGB}{220,0,0} 32 | \newcommand{\hcancel}[5]{% 33 | \tikz[baseline=(tocancel.base)]{ 34 | \node[inner sep=0pt,outer sep=0pt] (tocancel) {#1}; 35 | \draw[darkred, line width=1mm] ($(tocancel.south west)+(#2,#3)$) -- ($(tocancel.north east)+(#4,#5)$); 36 | }% 37 | }% 38 | 39 | \newcommand{\slogan}[1]{% 40 | \begin{center}% 41 | \setlength{\fboxrule}{2pt}% 42 | \setlength{\fboxsep}{-3pt}% 43 | {\usebeamercolor[fg]{item}\fbox{\usebeamercolor[fg]{normal 44 | text}\parbox{0.9\textwidth}{\begin{center}#1\end{center}}}}% 45 | \end{center}% 46 | } 47 | 48 | \renewcommand{\C}{\mathcal{C}} 49 | \newcommand{\D}{\mathcal{D}} 50 | \newcommand{\id}{\mathrm{id}} 51 | \newcommand{\Id}{\mathrm{Id}} 52 | \newcommand{\Hask}{\mathrm{Hask}} 53 | 54 | \setbeamertemplate{navigation symbols}{} 55 | \setbeamertemplate{headline}{} 56 | 57 | \setbeamertemplate{title page}[default][colsep=-1bp,rounded=false,shadow=false] 58 | \setbeamertemplate{frametitle}[default][colsep=-2bp,rounded=false,shadow=false,center] 59 | 60 | \newcommand*\oldmacro{}% 61 | \let\oldmacro\insertshorttitle% 62 | \renewcommand*\insertshorttitle{% 63 | \oldmacro\hfill\insertframenumber\,/\,\inserttotalframenumber\hfill} 64 | 65 | \newcommand{\hil}[1]{{\usebeamercolor[fg]{item}{\textbf{#1}}}} 66 | \setbeamertemplate{frametitle}{% 67 | \vskip1em% 68 | \leavevmode% 69 | \begin{beamercolorbox}[dp=1ex,center]{}% 70 | \usebeamercolor[fg]{item}{\textbf{\textsf{\Large \insertframetitle}}} 71 | \end{beamercolorbox}% 72 | } 73 | 74 | \setbeamertemplate{footline}{% 75 | \leavevmode% 76 | \hfill% 77 | \begin{beamercolorbox}[ht=2.25ex,dp=1ex,right]{}% 78 | \usebeamerfont{date in head/foot} 79 | \insertframenumber\,/\,\inserttotalframenumber\hspace*{1ex} 80 | \end{beamercolorbox}% 81 | \vskip0pt% 82 | } 83 | 84 | \newcommand{\backupstart}{ 85 | \newcounter{framenumberpreappendix} 86 | \setcounter{framenumberpreappendix}{\value{framenumber}} 87 | } 88 | \newcommand{\backupend}{ 89 | \addtocounter{framenumberpreappendix}{-\value{framenumber}} 90 | \addtocounter{framenumber}{\value{framenumberpreappendix}} 91 | } 92 | 93 | \setbeameroption{show notes} 94 | \setbeamertemplate{note page}[plain] 95 | 96 | \begin{document} 97 | 98 | \frame{\titlepage} 99 | 100 | \frame{\tableofcontents} 101 | 102 | \section{Spezifikation von Instruktionen} 103 | \begin{frame}[fragile]\frametitle{Gewünschte Instruktionen} 104 | \begin{minted}{haskell} 105 | type St = ... 106 | data StateI :: * -> * where 107 | Get :: StateI St 108 | Put :: St -> StateI () 109 | \end{minted} 110 | 111 | \vfill 112 | \slogan{Freie Funktoren und freie Monaden liefern ein allgemeines 113 | Konstruktionsrezept für Monaden mit gewünschter operationeller Semantik.} 114 | \end{frame} 115 | 116 | \begin{frame}[fragile]\frametitle{Gewünschte Instruktionen} 117 | \begin{minted}{haskell} 118 | type St = ... 119 | data StateI :: * -> * where 120 | Get :: StateI St 121 | Put :: St -> StateI () 122 | 123 | type Env = ... 124 | data ReaderI :: * -> * where 125 | Ask :: ReaderI Env 126 | 127 | type Log = ... 128 | data WriterI :: * -> * where 129 | Tell :: Log -> WriterI () 130 | \end{minted} 131 | \end{frame} 132 | 133 | \begin{frame}[fragile]\frametitle{Gewünschte Instruktionen} 134 | \begin{minted}{haskell} 135 | type Err = ... 136 | data ErrorI :: * -> * where 137 | Throw :: Err -> ErrorI a 138 | 139 | data IOI :: * -> * where 140 | PutStrLn :: String -> IOI () 141 | GetLine :: IOI String 142 | Exit :: IOI a 143 | \end{minted} 144 | \end{frame} 145 | 146 | 147 | \section{Freie Funktoren} 148 | \begin{frame}[fragile]\frametitle{Freie Funktoren} 149 | Wir können aus einem Typkonstruktor \texttt{t :: * -> *} auf unspektakulärste 150 | Art und Weise einen Funktor machen: 151 | 152 | \begin{minted}{haskell} 153 | class Functor f where 154 | fmap :: (a -> b) -> (f a -> f b) 155 | 156 | data FreeF t a = MkFreeF (exists r. (t r, r -> a)) 157 | data FreeF t a = forall r. MkFreeF (t r) (r -> a) 158 | -- MkFreeT :: t r -> (r -> a) -> FreeF t a 159 | 160 | liftF :: t a -> FreeF t a 161 | liftF x = MkFreeF x id 162 | 163 | instance Functor (FreeF t) where 164 | fmap phi (MkFreeF x h) = MkFreeF x (phi . h) 165 | \end{minted} 166 | \end{frame} 167 | 168 | \note{\justifying 169 | Wenn \texttt{t} ein Funktor \emph{wäre}, so könnte man eine Funktion 170 | \texttt{r -> a} zu einer Funktion \texttt{t r -> t a} liften. Wenn \texttt{t} 171 | kein Funktor ist, geht das nicht. 172 | \medskip 173 | 174 | Der freie Funktor \texttt{FreeF t} über \texttt{t} \emph{cheatet}: Ein Wert 175 | vom Typ \texttt{Free t a} besteht aus einem Wert \texttt{x :: t r} zusammen 176 | mit einer Funktion \texttt{f :: r -> a}. Anschaulich stellen wir uns diese 177 | Kombination als das vor, was \texttt{fmap f x} ergäbe, wenn \texttt{t} ein 178 | Funktor wäre. 179 | \medskip 180 | 181 | Die Implementierung von \texttt{fmap phi} für \texttt{FreeF t} ist dann rein 182 | \emph{formal}: Anstatt \texttt{phi} wirklich auf einen Wert vom Typ \texttt{t 183 | r} anzuwenden (was unmöglich ist), notieren wir uns nur die Information, dass 184 | \texttt{phi} anzuwenden \emph{wäre}. 185 | \par 186 | } 187 | 188 | \note{\justifying 189 | Das Paar bestehend aus dem \emph{freien Funktor~\texttt{FreeF t} über~\texttt{t}} 190 | und der Funktion~\texttt{liftF} erfüllt folgende \emph{universelle 191 | Eigenschaft}: 192 | \medskip 193 | 194 | Ist~\texttt{G} irgendein Funktor und~\texttt{phi :: t a -> G a} irgendeine 195 | Funktion, so existiert genau eine Funktion~\texttt{phi' :: FreeF t a -> G a} 196 | mit~\texttt{phi' . liftF = phi}. 197 | \[ \xymatrix{ 198 | \texttt{t} \ar@{=>}[rr]^{\texttt{phi}} \ar@{=>}[rd]_{\texttt{liftF}} && G \\ 199 | & \texttt{FreeF t} \ar@{==>}[ru]_{\texttt{phi'}} 200 | } \] 201 | } 202 | 203 | \note{\justifying 204 | Einen Typkonstruktor~\texttt{t :: * -> *} kann man auch als einen 205 | Funktor~$\Hask_0 \to \Hask$ auffassen. Dabei hat die Kategorie~$\Hask_0$ 206 | dieselben Objekte wie~$\Hask$, enthält aber nur Identitätsmorphismen. 207 | \medskip 208 | 209 | Der freie Funktor über~\texttt{t} ist dann die \emph{Links-Kan-Erweiterung} 210 | von~\texttt{t} längs der Inklusion~$\Hask_0 \hookrightarrow \Hask$. 211 | Die angegebene Definition von~\texttt{FreeF t} ist nichts anderes als die 212 | \emph{Koendeformel} für Links-Kan-Erweiterungen. 213 | \medskip 214 | \[ \xymatrixcolsep{4pc}\xymatrixrowsep{4pc}\xymatrix{ 215 | \Hask \ar@{-->}[rd]^{\texttt{FreeF t}} \\ 216 | \Hask_0 \ar[r]^{\texttt{t}} \ar@{^{(}->}[u] & \Hask 217 | } \] 218 | \medskip 219 | 220 | \[ 221 | \texttt{FreeF t a} = \int^{r \in \Hask_0} (\texttt{t r}, \texttt{r -> a}) 222 | \] 223 | } 224 | 225 | \begin{frame}[plain] 226 | \begin{center} 227 | \includegraphics[height=\textheight]{images/kan-extension} 228 | \end{center} 229 | \end{frame} 230 | 231 | \begin{frame}[fragile]\frametitle{Beispiel: Zustand} 232 | \begin{minted}{haskell} 233 | class Functor f where 234 | fmap :: (a -> b) -> (f a -> f b) 235 | 236 | data FreeF t a = forall r. MkFreeF (t r) (r -> a) 237 | 238 | data StateI :: * -> * where 239 | Get :: StateI St 240 | Put :: St -> StateI () 241 | 242 | -- `FreeF StateI` ist isomorph zu: 243 | data StateF a = Get (St -> a) | Put St a 244 | \end{minted} 245 | \end{frame} 246 | 247 | \note{\justifying 248 | Offensichtlich wird \texttt{StateF} zu einem Funktor. Das 249 | zugehörige~\texttt{fmap} ist recht langweilig: 250 | 251 | \inputminted{haskell}{images/statef-functor.hs} 252 | 253 | Genauso langweilig sind die Funktor-Instanzen von anderen Typkonstruktoren 254 | der Form~\texttt{FreeF t}.\par 255 | } 256 | 257 | \section{Freie Monaden} 258 | \begin{frame}[fragile]\frametitle{Freie Monaden} 259 | Wir können aus einem Funktor \texttt{f :: * -> *} auf unspektakulärste 260 | Art und Weise eine Monade machen: 261 | \begin{minted}{haskell} 262 | data FreeM f a = Pure a | Roll (f (FreeM f a)) 263 | 264 | instance (Functor f) => Monad (FreeM f) where 265 | return x = Pure x 266 | 267 | Pure x >>= k = k x 268 | Roll u >>= k = Roll (fmap (>>= k) u) 269 | \end{minted} 270 | \end{frame} 271 | 272 | \note{\justifying 273 | Mehr zu freien Monaden in einem separaten Foliensatz: 274 | \medskip 275 | 276 | \url{http://curry-club-augsburg.de/posts/2015-08-14-ankuendigung-siebtes-treffen.html} 277 | } 278 | 279 | \begin{frame}[fragile]\frametitle{Zusammengesetzt} 280 | \begin{minted}{haskell} 281 | data FreeF t a = forall r. MkFreeF (t r) (r -> a) 282 | data FreeM f a = Pure a | Roll (f (FreeM f a)) 283 | 284 | -- Also ist `FreeM (FreeF t) a` isomorph zu: 285 | data Prog t a = 286 | Pure a | forall r. Step (t r) (r -> Prog t a) 287 | 288 | data StateI :: * -> * where 289 | Get :: StateI St 290 | Put :: St -> StateI () 291 | -- `Prog StateI a` ist isomorph zu: 292 | data StateProg a 293 | = Pure a 294 | | Get (St -> StateProg a) 295 | | Put St (StateProg a) 296 | \end{minted} 297 | \end{frame} 298 | 299 | \note{\justifying 300 | Auch ohne die Motivation über freie Funktoren und freie Monaden besitzt 301 | \texttt{Prog} eine anschauliche Bedeutung. Wir können uns einen Wert vom 302 | Typ~\texttt{Prog t a} als eine Folge von Instruktionen vorstellen, die 303 | schlussendlich einen Wert vom Typ~\texttt{a} produziert. Welche Instruktionen 304 | vorkommen können, entscheidet~\texttt{t}. 305 | \medskip 306 | 307 | Ein Wert vom Typ~\texttt{Prog t a} ist entweder von der Form~\texttt{Pure x}, 308 | also ein triviale Folge von Instruktionen mit Produktionswert~\texttt{x}, 309 | oder von der Form~\texttt{Step u k}. Dabei kodiert~\texttt{u} eine 310 | Instruktion, die bei Ausführung einen Wert~\texttt{x :: r} produziert, und 311 | die Continuation~\texttt{k :: r -> Prog t a} gibt an, wie es danach weitergehen 312 | soll. 313 | \par 314 | } 315 | 316 | \begin{frame}[fragile]\frametitle{Operationelle Semantik} 317 | \begin{minted}{haskell} 318 | data StateProg a 319 | = Pure a 320 | | Get (St -> StateProg a) 321 | | Put St (StateProg a) 322 | 323 | interpret :: StateProg a -> (St -> (a,St)) 324 | interpret (Pure x) st = (x, st) 325 | interpret (Get k) st = interpret (k st) st 326 | interpret (Put st' u) st = interpret u st' 327 | \end{minted} 328 | \end{frame} 329 | 330 | \begin{frame}[fragile]\frametitle{In Kürze} 331 | \begin{minted}{haskell} 332 | -- Die freie Monade über dem freien Funktor über t: 333 | data Prog t a = 334 | Pure a | forall r. Step (t r) (r -> Prog t a) 335 | \end{minted} 336 | 337 | \begin{itemize} 338 | \item Werte vom Typ \texttt{Prog t a} sind rein syntaktische Beschreibungen 339 | von Aktionsfolgen. 340 | Insbesondere gelten keinerlei besondere Rechenregeln, wie zum 341 | Beispiel \texttt{Put x (Put x' m) == Put x' m}. 342 | \item Erst durch Angabe eines Interpreters wird die Konstruktion zum Leben 343 | erweckt. 344 | \item Man kann leicht Instruktionsspezifikationen miteinander kombinieren! 345 | \item In der naiven Implementierung: Effizienzproblem mit linksassoziativer 346 | Verwendung von \texttt{(>{}>=)} 347 | \end{itemize} 348 | \end{frame} 349 | 350 | \note{\justifying 351 | Ein und dieselbe freie Monade kann mehrere verschiedene Interpreter zulassen. 352 | Zum Beispiel kann man in Produktion einen Interpreter verwenden, der eine 353 | Datenbank anspricht, und zum Testen einen, der fiktive Werte vortäuscht 354 | (Mocking). 355 | \medskip 356 | 357 | Siehe unbedingt auch: 358 | \begin{itemize} 359 | \item Heinrich Apfelmus. \emph{The Operational Monad Tutorial}. 2010. 360 | 361 | \url{http://apfelmus.nfshost.com/articles/operational-monad.html} 362 | \end{itemize} 363 | } 364 | 365 | \begin{frame}[fragile]\frametitle{Beispiel: Einfaches Multitasking} 366 | \begin{minted}{haskell} 367 | data ProcessI :: (* -> *) -> * -> * where 368 | Lift :: m a -> ProcessI m a 369 | Stop :: ProcessI m a 370 | Fork :: ProcessI m Bool -- wie in Unix 371 | Yield :: ProcessI m () 372 | 373 | -- Interpreter, der nur bei Aufruf von `Yield` die 374 | -- Kontrolle an den nächsten Prozess weitergibt 375 | runCoop :: (Monad m) => Prog (ProcessI m) a -> m () 376 | 377 | -- Interpreter, der nach jeder Aktion in der Basis- 378 | -- monade die Kontrolle weitergibt 379 | runForced :: (Monad m) => Prog (ProcessI m) a -> m () 380 | \end{minted} 381 | \end{frame} 382 | 383 | \note{\justifying 384 | Siehe Beispielcode: 385 | \medskip 386 | 387 | \url{https://github.com/iblech/vortrag-haskell/blob/master/effektsysteme.hs} 388 | } 389 | 390 | 391 | \section{Einschub: Koprodukt von Monaden} 392 | 393 | \begin{frame}[fragile]\frametitle{Einschub: Koprodukt von Monaden} 394 | Sind \texttt{m} und \texttt{n} Monaden, so kann man eine Monade bauen, die 395 | die Fähigkeiten von \texttt{m} und \texttt{n} vereint. Diese heißt 396 | \emph{Koprodukt} von \texttt{m} und \texttt{n}. 397 | \medskip 398 | 399 | \small 400 | \begin{minted}{haskell} 401 | data Sum m n a = Inl (m a) | Inr (n a) 402 | type Coprod m n a = Prog (Sum m n) a 403 | 404 | -- Coprod m n vereint m und n: 405 | inl :: m a -> Coprod m n a inr :: n a -> Coprod m n a 406 | inl x = Step (Inl x) Pure inr x = Step (Inr x) Pure 407 | 408 | -- Ausführung mit (universelle Eigenschaft): 409 | elim :: (Monad m, Monad n, Monad s) 410 | => (m a -> s a) -> (n a -> s a) 411 | -> (Coprod m n a -> s a) 412 | elim = ... 413 | \end{minted} 414 | \end{frame} 415 | 416 | \begin{frame}[fragile]\frametitle{Beispiel: State s $\amalg$ Error e} 417 | \begin{minted}{haskell} 418 | type Err e = Either e 419 | 420 | ex :: Coprod (State Int) (Err String) Int 421 | ex = do 422 | st <- inl get 423 | if st <= 0 then inr (Left "Fehler") else do 424 | inl $ put (st - 1) 425 | return $ st^2 + st + 1 426 | \end{minted} 427 | \end{frame} 428 | 429 | \note{\justifying 430 | Ausführung durch Angabe einer Monade, in die man \texttt{State Int} und 431 | \texttt{Err String} einbetten kann -- zum Beispiel \texttt{IO}: 432 | 433 | \inputminted{haskell}{images/run-coproduct.hs} 434 | } 435 | 436 | 437 | \section{Effektsysteme} 438 | 439 | \begin{frame}[fragile]\frametitle{Effektsysteme} 440 | \slogan{Effektsysteme lösen das Problem der fehlenden Kompositionalität von Monaden.} 441 | 442 | Die Monade \texttt{Eff r} ist wie \texttt{Prog t}, nur 443 | \medskip 444 | 445 | \begin{itemize} 446 | \item performant bezüglich \texttt{(>{}>=)} und 447 | \item mit \texttt{r} als \emph{Liste} von möglichen Instruktionen (auf 448 | Typebene) anstatt mit \texttt{t} als Instruktionen kodierenden 449 | \emph{Typkonstruktor}. 450 | \end{itemize} 451 | 452 | \begin{minted}{haskell} 453 | ask :: (Member (Reader env) r) => Eff r env 454 | get :: (Member (State st) r) => Eff r st 455 | put :: (Member (State st) r) => st -> Eff r () 456 | -- Typen schreiben r nicht eindeutig vor! 457 | \end{minted} 458 | \end{frame} 459 | 460 | \note{\justifying 461 | Wenn man nachträglich seinen Transformerstack ändert, muss man viele 462 | Typsignaturen und gelegentlich auch einige Codefragmente anpassen (zum 463 | Beispiel \texttt{lift} in \texttt{lift . lift} ändern). Das ist mühsam. 464 | \medskip 465 | 466 | Bei Verwendung von \texttt{Eff} muss man das nicht. 467 | \medskip 468 | 469 | Werte vom Typ \texttt{Eff r a} sind wie bei \texttt{Prog t a} auch nur 470 | \emph{Beschreibungen} von auszuführenden Aktionen; erst durch Angabe von 471 | Interpretern können sie ausgeführt werden. Interpreter können leicht 472 | miteinander kombiniert werden. 473 | \par 474 | } 475 | 476 | \begin{frame}[fragile]\frametitle{Interpreter} 477 | \begin{minted}{haskell} 478 | type Env = ... 479 | data Reader :: * -> * where 480 | Get :: Reader Env 481 | 482 | ask :: (Member Reader r) => Eff r Env 483 | ask = Roll (inj Get) (tsingleton Pure) 484 | 485 | runReader :: Env -> Eff (Reader ’: r) a -> Eff r a 486 | runReader e m = loop m where 487 | loop (Pure x) = return x 488 | loop (Roll u q) = case decomp u of 489 | Right Get -> loop $ qApp q e 490 | Left u -> Roll u (tsingleton (qComp q loop)) 491 | -- kürzer: 492 | runReader e = handleRelay return (\Get k -> k e) 493 | \end{minted} 494 | \end{frame} 495 | 496 | \note{\justifying 497 | Siehe unbedingt: 498 | \begin{itemize} 499 | \item Oleg Kiselyov, Hiromi Ishii. \emph{Freer Monads, More Extensible 500 | Effects.} 2015. 501 | 502 | \url{http://okmij.org/ftp/Haskell/extensible/more.pdf} 503 | 504 | \item Oleg Kiselyov, Amr Sabry, Cameron Swords. 505 | \emph{Extensible Effects. An Alternative to Monad Transformers.} 2013. 506 | 507 | \url{http://okmij.org/ftp/Haskell/extensible/exteff.pdf} 508 | 509 | \item Andrej Bauer, Matija Pretnar. \emph{Programming with Algebraic 510 | Effects and Handlers.} 2012. 511 | 512 | \url{http://arxiv.org/abs/1203.1539} 513 | \end{itemize} 514 | } 515 | 516 | \end{document} 517 | -------------------------------------------------------------------------------- /fixpunkt.gnuplot: -------------------------------------------------------------------------------- 1 | set style line 1 linecolor rgb '#000000' linetype 1 linewidth 2 2 | set style line 2 linecolor rgb '#9600ff' linetype 1 linewidth 4 3 | set style line 3 linecolor rgb '#4444ff' linetype 1 linewidth 4 4 | 5 | unset border 6 | set grid 7 | set xtics ("0" 0, "1" 1) 8 | set ytics ("0" 0, "1" 1) 9 | set xrange [ 0 : 1.9 ] 10 | set yrange [ 0 : 3 ] 11 | set xzeroaxis ls 1 lw 3 12 | set yzeroaxis ls 1 lw 3 13 | set samples 10000 14 | 15 | set terminal pdf size 10cm, 4cm dashed 16 | set output "fixpunkt.pdf" 17 | 18 | plot sqrt(x) w l ls 2, x w l ls 3 19 | -------------------------------------------------------------------------------- /fixpunkt.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/fixpunkt.pdf -------------------------------------------------------------------------------- /fixup-minted.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -i -p 2 | 3 | use warnings; 4 | use strict; 5 | 6 | s/::/\\ensuremath{::}/g; 7 | s/=\\PYGdefaultZgt{}|=>/\\ensuremath{\\Rightarrow}/g; 8 | s/\\PYGdefaultZhy{}\\PYGdefaultZgt{}|->/\\ensuremath{\\rightarrow}/g; 9 | s/<-/\\ensuremath{\\leftarrow}/g; 10 | s/>=/\\ensuremath{\\geq}/g; 11 | s/<=/\\ensuremath{\\leq}/g; 12 | s/>>/\\ensuremath{\\gg}/g; 13 | -------------------------------------------------------------------------------- /folien.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/folien.pdf -------------------------------------------------------------------------------- /fractran.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Data.List 4 | import Data.Ratio 5 | import Control.Monad.State 6 | import Control.Monad.Writer 7 | import Test.QuickCheck 8 | import Control.Exception 9 | 10 | type PositiveRat = Rational 11 | type Nat = Integer 12 | type PositiveNat = Integer 13 | type Program = [PositiveRat] 14 | 15 | run :: Program -> PositiveNat -> [PositiveNat] 16 | run p n = n : maybe [] (run p) (step p n) 17 | 18 | step :: Program -> PositiveNat -> Maybe PositiveNat 19 | step [] _ = Nothing 20 | step (x:xs) n 21 | | Just m <- isInteger (fromIntegral n * x) = Just m 22 | | otherwise = step xs n 23 | 24 | isInteger :: Rational -> Maybe Integer 25 | isInteger x 26 | | denominator x == 1 = Just $ numerator x 27 | | otherwise = Nothing 28 | 29 | exPrimes :: Program 30 | exPrimes = [17/91, 78/85, 19/51, 23/38, 29/33, 77/29, 95/23, 77/19, 1/17, 11/13, 13/11, 15/14, 15/2, 55/1] 31 | 32 | primeFactors :: PositiveNat -> [PositiveNat] 33 | primeFactors = pf primes 34 | where 35 | pf ps@(p:ps') n 36 | | p * p > n = if n == 1 then [] else [n] 37 | | r == 0 = p : pf ps q 38 | | otherwise = pf ps' n 39 | where (q,r) = n `divMod` p 40 | 41 | primes :: [PositiveNat] 42 | primes = 2 : filter (null . tail . primeFactors) [3,5..] 43 | 44 | encode :: [Nat] -> PositiveNat 45 | encode ns = product $ zipWith (^) primes ns 46 | 47 | decode :: PositiveNat -> [Nat] 48 | decode m = if m == 1 then [] else go primes 0 m 49 | where 50 | go ps@(p:ps') i n 51 | | r == 0 = go ps (i+1) q 52 | | n == 1 = [i] 53 | | otherwise = i : go ps' 0 n 54 | where (q,r) = n `divMod` p 55 | 56 | encode' :: [Integer] -> PositiveRat 57 | encode' ns = product $ zipWith (^^) (map fromIntegral primes) ns 58 | 59 | decode' :: PositiveRat -> [Integer] 60 | decode' m = decode (numerator m) <-> decode (denominator m) 61 | where 62 | (<->) = zipWithDefault (-) 0 63 | 64 | prop1 :: Positive Nat -> Bool 65 | prop1 n = let n' = fromIntegral n in encode (decode n') == n' 66 | 67 | prop2 :: [Positive Nat] -> Bool 68 | prop2 xs = let xs' = map fromIntegral xs in decode (encode xs') == xs' 69 | 70 | prop1' :: Positive Integer -> Positive Integer -> Bool 71 | prop1' x y = let q = fromIntegral x % fromIntegral y in encode' (decode' q) == q 72 | 73 | prop2' :: [Integer] -> Bool 74 | prop2' xs = and $ zipWithDefault (==) 0 xs $ decode' (encode' xs) 75 | 76 | zipWithDefault :: (a -> a -> b) -> a -> [a] -> [a] -> [b] 77 | zipWithDefault (<*>) z [] ys = map (z <*>) ys 78 | zipWithDefault (<*>) z xs [] = map (<*> z) xs 79 | zipWithDefault (<*>) z (x:xs) (y:ys) = x <*> y : zipWithDefault (<*>) z xs ys 80 | 81 | -- if $n > 0 then ($n, $m) <- (0, $m + $n) 82 | pAdd n m = assert (n /= m) [ m % n ] 83 | 84 | -- if $n > 0 then ($n, $m, $p) <- (0, $m + $n, $p + $n) 85 | pAdd' n m p = assert (n /= m && n /= p) [ m * p % n ] 86 | 87 | -- if $n > 0 then ($n, $m) <- (0, $m * $n) 88 | pMul = undefined 89 | -------------------------------------------------------------------------------- /freie-monaden.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RankNTypes, ExistentialQuantification, GADTs #-} 2 | module Main where 3 | 4 | import Control.Monad (join) 5 | 6 | -------------------------------------------------------------------------------- 7 | -- Freie Monaden 8 | 9 | data Free f a 10 | = Pure a 11 | | Roll (f (Free f a)) 12 | 13 | liftF :: (Functor f) => f a -> Free f a 14 | liftF = Roll . fmap Pure 15 | 16 | instance (Functor f) => Functor (Free f) where 17 | fmap h (Pure x) = Pure (h x) 18 | fmap h (Roll u) = Roll (fmap (fmap h) u) 19 | 20 | instance (Functor f) => Monad (Free f) where 21 | return x = Pure x 22 | m >>= k = join_ $ fmap k m 23 | where 24 | join_ (Pure u) = u 25 | join_ (Roll v) = Roll (fmap join_ v) 26 | 27 | can :: (Functor f, Monad m) 28 | => (forall a. f a -> m a) 29 | -> (forall a. Free f a -> m a) 30 | can phi (Pure x) = return x 31 | can phi (Roll u) = join $ phi . fmap (can phi) $ u 32 | -- oder: join $ fmap (can phi) . phi $ u 33 | 34 | 35 | -------------------------------------------------------------------------------- 36 | -- Anwendung: State als Quotient einer freien Monade 37 | 38 | data StateInstr s r 39 | = Put s r 40 | | Get (s -> r) 41 | 42 | type State s = Free (StateInstr s) 43 | -- ein Wert dieses Typs könnte so aussehen: 44 | -- 45 | -- Roll $ Put x $ Roll $ Put x' $ Roll $ Get $ \x'' -> Pure (42+x'') 46 | 47 | get :: State s s 48 | get = Roll $ Get Pure 49 | 50 | put :: s -> State s () 51 | put x = Roll $ Put x $ Pure () 52 | 53 | evalState :: State s a -> s -> (a,s) 54 | evalState (Pure x) s = (x,s) 55 | evalState (Roll u) s 56 | | Get k <- u = evalState (k s) s 57 | | Put s' u' <- u = evalState u' s' 58 | 59 | 60 | -------------------------------------------------------------------------------- 61 | -- Anwendung: Reader als Quotient einer freien Monade 62 | 63 | data ReaderInstr e r 64 | = Ask (e -> r) 65 | 66 | type Reader e = Free (ReaderInstr e) 67 | 68 | ask :: Reader e e 69 | ask = Roll $ Ask Pure 70 | 71 | local :: e -> Reader e a -> Reader e a 72 | local e m = Pure $ evalReader m e 73 | 74 | evalReader :: Reader e a -> e -> a 75 | evalReader (Pure x) e = x 76 | evalReader (Roll u) e 77 | | Ask k <- u = evalReader (k e) e 78 | 79 | 80 | -------------------------------------------------------------------------------- 81 | -- "Noch freier" 82 | 83 | data FreeFunctor f a = forall x. MkFreeF (f x) (x -> a) 84 | -- Links-Kan-Erweiterung von f längs der Inklusion Hask_0 --> Hask. 85 | -- Ist der "freie Funktor über f". 86 | 87 | univ :: (Functor g) => (forall a. f a -> g a) -> (FreeFunctor f a -> g a) 88 | univ phi (MkFreeF u k) = fmap k (phi u) 89 | 90 | 91 | -------------------------------------------------------------------------------- 92 | -- Anwendung: State noch freier 93 | 94 | data StateInstr' s r where 95 | Get' :: StateInstr' s s 96 | Put' :: s -> StateInstr' s () 97 | 98 | instance Functor (FreeFunctor f) where 99 | fmap phi (MkFreeF u k) = MkFreeF u (phi . k) 100 | 101 | type State' s = Free (FreeFunctor (StateInstr' s)) 102 | 103 | evalState' :: State' s a -> s -> (a,s) 104 | evalState' (Pure x) s = (x,s) 105 | evalState' (Roll (MkFreeF m k)) s = 106 | case m of 107 | Get' -> evalState' (k s) s 108 | Put' s' -> evalState' (k ()) s' 109 | -------------------------------------------------------------------------------- /freie-monaden.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/freie-monaden.pdf -------------------------------------------------------------------------------- /freie-monaden.tex: -------------------------------------------------------------------------------- 1 | % Kompilieren mit: TEXINPUTS=minted/source: pdflatex -shell-escape % 2 | \documentclass[12pt,compress,ngerman,utf8,t]{beamer} 3 | \usepackage[ngerman]{babel} 4 | \usepackage{ragged2e} 5 | \usepackage{comment} 6 | \usepackage{minted} 7 | \usepackage{wasysym} 8 | \usepackage{booktabs} 9 | \usepackage{tikz} 10 | \usetikzlibrary{calc} 11 | \usepackage[all]{xy} 12 | \usepackage[protrusion=true,expansion=false]{microtype} 13 | 14 | \DeclareSymbolFont{extraup}{U}{zavm}{m}{n} 15 | \DeclareMathSymbol{\varheart}{\mathalpha}{extraup}{86} 16 | \DeclareMathSymbol{\vardiamond}{\mathalpha}{extraup}{87} 17 | 18 | \DeclareUnicodeCharacter{2237}{$\dblcolon$} 19 | \DeclareUnicodeCharacter{21D2}{$\Rightarrow$} 20 | \DeclareUnicodeCharacter{2192}{$\rightarrow$} 21 | 22 | \title[Freie Monaden]{\smiley{} Monaden als Monoidobjekte \smiley} 23 | \author[Augsburger Curry Club]{ 24 | \includegraphics[scale=0.1]{images/a-monad-is-just-1} \\\ \\ 25 | Ingo Blechschmidt \\[0.1em] \scriptsize\texttt{}} 26 | \date[2017-03-17]{\vspace*{-1.5em}\scriptsize Hannover.FP \\ 17. 27 | März 2017} 28 | 29 | \useinnertheme[shadow=true]{rounded} 30 | \useoutertheme{split} 31 | \usecolortheme{orchid} 32 | \usecolortheme{whale} 33 | \setbeamerfont{block title}{size={}} 34 | 35 | \useinnertheme{rectangles} 36 | 37 | \usecolortheme{seahorse} 38 | \definecolor{mypurple}{RGB}{150,0,255} 39 | \setbeamercolor{structure}{fg=mypurple} 40 | \definecolor{myred}{RGB}{150,0,0} 41 | \setbeamercolor*{title}{bg=myred,fg=white} 42 | \setbeamercolor*{titlelike}{bg=myred,fg=white} 43 | 44 | \usefonttheme{serif} 45 | \usepackage[T1]{fontenc} 46 | \usepackage{libertine} 47 | 48 | \definecolor{darkred}{RGB}{220,0,0} 49 | \newcommand{\hcancel}[5]{% 50 | \tikz[baseline=(tocancel.base)]{ 51 | \node[inner sep=0pt,outer sep=0pt] (tocancel) {#1}; 52 | \draw[darkred, line width=1mm] ($(tocancel.south west)+(#2,#3)$) -- ($(tocancel.north east)+(#4,#5)$); 53 | }% 54 | }% 55 | 56 | \renewcommand{\C}{\mathcal{C}} 57 | \newcommand{\D}{\mathcal{D}} 58 | \newcommand{\id}{\mathrm{id}} 59 | \newcommand{\Id}{\mathrm{Id}} 60 | \newcommand{\Hask}{\mathrm{Hask}} 61 | 62 | \setbeamertemplate{navigation symbols}{} 63 | %\setbeamertemplate{headline}{} 64 | 65 | \setbeamertemplate{title page}[default][colsep=-1bp,rounded=false,shadow=false] 66 | \setbeamertemplate{frametitle}[default][colsep=-2bp,rounded=false,shadow=false,center] 67 | 68 | \newcommand*\oldmacro{}% 69 | \let\oldmacro\insertshorttitle% 70 | \renewcommand*\insertshorttitle{% 71 | \oldmacro\hfill\insertframenumber\,/\,\inserttotalframenumber\hfill} 72 | 73 | \newcommand{\hil}[1]{{\usebeamercolor[fg]{item}{\textbf{#1}}}} 74 | \setbeamertemplate{frametitle}{% 75 | \vskip0.5em% 76 | \leavevmode% 77 | \begin{beamercolorbox}[dp=1ex,center]{}% 78 | \usebeamercolor[fg]{item}{\textbf{\Large \insertframetitle}} 79 | \end{beamercolorbox}% 80 | } 81 | 82 | \setbeamertemplate{footline}{% 83 | \leavevmode% 84 | \hfill% 85 | \begin{beamercolorbox}[ht=2.25ex,dp=1ex,right]{}% 86 | \usebeamerfont{date in head/foot} 87 | \insertframenumber\,/\,\inserttotalframenumber\hspace*{1ex} 88 | \end{beamercolorbox}% 89 | \vskip0pt% 90 | } 91 | 92 | \newcommand{\backupstart}{ 93 | \newcounter{framenumberpreappendix} 94 | \setcounter{framenumberpreappendix}{\value{framenumber}} 95 | } 96 | \newcommand{\backupend}{ 97 | \addtocounter{framenumberpreappendix}{-\value{framenumber}} 98 | \addtocounter{framenumber}{\value{framenumberpreappendix}} 99 | } 100 | 101 | \setbeameroption{hide notes} 102 | \setbeamertemplate{note page}[plain] 103 | 104 | \begin{document} 105 | 106 | \frame{\titlepage} 107 | 108 | \frame{\tableofcontents} 109 | 110 | \section{Monoide} 111 | 112 | \subsection{Definition und Beispiele} 113 | 114 | \begin{frame}[fragile]\frametitle{Monoide} 115 | Ein \hil{Monoid} besteht aus 116 | \begin{itemize} 117 | \item einer Menge~$M$, 118 | \item einer Abbildung~$({\circ}) : M \times M \to M$ und 119 | \item einem ausgezeichneten Element~$e \in M$, 120 | \end{itemize} 121 | sodass die \hil{Monoidaxiome} gelten: Für alle~$x,y,z \in M$ 122 | \begin{itemize} 123 | \item $x \circ (y \circ z) = (x \circ y) \circ z$, 124 | \item $e \circ x = x$, 125 | \item $x \circ e = x$. 126 | \end{itemize} 127 | 128 | \visible<2>{\begin{center} 129 | \hil{Beispiele:} \\ 130 | natürliche Zahlen, Listen, Endomorphismen, 131 | Matrizen, \ldots 132 | \\[1em] 133 | \hil{Nichtbeispiele:} \\ 134 | natürliche Zahlen mit Subtraktion, 135 | nichtleere Listen, \ldots 136 | \end{center}} 137 | 138 | \vspace*{-22em} 139 | \begin{columns} 140 | \begin{column}{0.65\textwidth} 141 | \end{column} 142 | \begin{column}{0.4\textwidth} 143 | \scriptsize\begin{block}{} 144 | \begin{minted}{haskell} 145 | class Monoid m where 146 | (<>) :: m -> m -> m 147 | unit :: m 148 | \end{minted} 149 | \end{block} 150 | \end{column} 151 | \end{columns} 152 | \end{frame} 153 | 154 | \note{ 155 | \begin{itemize} 156 | \justifying 157 | \item Die natürlichen Zahlen bilden mit der Addition als Verknüpfung und der 158 | Null als ausgezeichnetes Element einen Monoid. 159 | \item Die natürlichen Zahlen bilden mit der Multiplikation als Verknüpfung 160 | und der Eins als ausgezeichnetes Element einen Monoid. 161 | \item Die Menge~$X^\star$ der endlichen Listen mit Einträgen aus einer 162 | Menge~$X$ (in Haskell also sowas wie~\texttt{[X]}, wobei da auch unendliche 163 | und partiell definierte Listen dabei sind) bildet mit der Konkatenation von 164 | Listen als Verknüpfung und der leeren Liste als ausgezeichnetes Element 165 | einen Monoid. 166 | \item Ist~$X$ irgendeine Menge, so bildet die Menge aller Abbildungen~$X 167 | \to X$ mit der Abbildungskomposition als Verknüpfung und der 168 | Identitätsabbildung als ausgezeichnetes Element einen Monoid. 169 | \item Die natürlichen Zahlen bilden mit der Subtraktionen keinen Monoid, da 170 | die Differenz zweier natürlicher Zahlen nicht immer wieder eine natürliche 171 | Zahl ist. Auch mit den ganzen Zahlen klappt es nicht, da die Subtraktion 172 | nicht assoziativ ist: $1 - (2 - 3) \neq (1 - 2) - 3$. 173 | \end{itemize} 174 | } 175 | 176 | \begin{frame}\frametitle{Axiome in Diagrammform} 177 | \[ \xymatrixcolsep{4pc}\xymatrixrowsep{4pc}\xymatrix{ 178 | M \times M \times M \ar[r]^{\id \times ({\circ})} \ar[d]_{({\circ}) \times \id} & M \times M 179 | \ar[d]^{({\circ})} \\ 180 | M \times M \ar[r]_{({\circ})} & M 181 | } \] 182 | \medskip 183 | \[ \xymatrixcolsep{4pc}\xymatrixrowsep{4pc}\xymatrix{ 184 | & M \\ 185 | M \ar[r]\ar[ru] & M \times M \ar[u] & \ar[l]\ar[lu] M 186 | } \] 187 | \end{frame} 188 | 189 | \note{\justifying 190 | Beide Diagramme sind Diagramme in der Kategorie der Mengen, d.\,h. die 191 | beteiligten Objekte~$M$, $M \times M$ und~$M \times M \times M$ sind Mengen 192 | und die vorkommenden Pfeile sind Abbildungen. Wer möchte, kann aber auch 193 | vorgeben, dass~$M$ ein Typ in Haskell ist (statt~$M \times M$ muss man 194 | dann~\texttt{(M,M)} denken) und dass die Pfeile Haskell-Funktionen sind. 195 | \medskip 196 | 197 | Das obere Diagramm ist wie folgt zu lesen. 198 | \medskip 199 | 200 | Ein beliebiges Element aus~$M \times M \times M$ hat die Form~$(x,y,z)$, 201 | wobei~$x$, $y$ und~$z$ irgendwelche Elemente aus~$M$ sind. Bilden wir ein 202 | solches Element nach rechts ab, so erhalten wir~$(x,y \circ z)$. Bilden wir 203 | dieses weiter nach unten ab, so erhalten wir~$x \circ (y \circ z)$. 204 | \medskip 205 | 206 | Wir können aber auch den anderen Weg gehen: Bilden wir~$(x,y,z)$ erst nach 207 | unten ab, so erhalten wir~$(x \circ y,z)$. Bilden wir dieses Element weiter 208 | nach rechts ab, so erhalten wir~$(x \circ y) \circ z$. 209 | \medskip 210 | 211 | Fazit: Genau dann \emph{kommutiert das Diagramm} -- das heißt beide Wege 212 | liefern gleiche Ergebnisse -- wenn die Rechenregel $x \circ (y \circ z) = (x 213 | \circ y) \circ z$ für alle Elemente~$x,y,z \in M$ erfüllt ist. 214 | \par 215 | } 216 | 217 | \note{\justifying 218 | Die Pfeile auf dem unteren Diagramm sind nicht beschriftet. Hier die 219 | Erklärung, was gemeint ist. 220 | \medskip 221 | 222 | Wir betrachten dazu ein beliebiges Element~$x \in M$ (untere linke Ecke im 223 | Diagramm). Nach rechts abgebildet erhalten wir~$(e,x)$. Dieses Element weiter 224 | nach oben abgebildet ergibt~$e \circ x$. 225 | \medskip 226 | 227 | Der direkte Weg mit dem Nordost verlaufenden Pfeil ergibt~$x$. 228 | \medskip 229 | 230 | Das linke Teildreieck kommutiert also genau dann, wenn die Rechenregel~$e 231 | \circ x = x$ für alle~$x \in M$ erfüllt ist. Analog kommutiert das rechte 232 | Teildreieck genau dann, wenn~$x \circ e = x$ für alle~$x \in M$. 233 | \par 234 | } 235 | 236 | \note{\justifying 237 | Wieso der Umstand mit der Diagrammform der Axiome? Das hat verschiedene 238 | schwache Gründe (es ist cool), aber auch einen starken inhaltlichen: Ein 239 | Diagramm dieser Art kann man nicht nur in der Kategorie interpretieren, in 240 | der es ursprünglich gedacht war (also der Kategorie der Mengen). Man kann es 241 | auch in anderen Kategorien interpretieren. Wählt man dazu speziell eine 242 | Kategorie von Endofunktoren, so erhält man die Definition einer Monade. 243 | \par 244 | } 245 | 246 | \begin{frame}[fragile]\frametitle{Monoidhomomorphismen} 247 | Eine Abbildung~$\varphi : M \to N$ zwischen Monoiden heißt genau dann 248 | \hil{Monoidhomomorphismus}, wenn 249 | \begin{itemize} 250 | \item $\varphi(e) = e$ und 251 | \item $\varphi(x \circ y) = \varphi(x) \circ \varphi(y)$ für alle~$x,y \in M$. 252 | \end{itemize} 253 | 254 | \begin{center} 255 | \hil{Beispiele:} \\ 256 | \mintinline{haskell}{length :: [a] -> Int} \\ 257 | \mintinline{haskell}{sum :: [Int] -> Int} \\[1em] 258 | \hil{Nichtbeispiele:} \\ 259 | \mintinline{haskell}{reverse :: [a] -> [a]} \\ 260 | \mintinline{haskell}{head :: [a] -> a} \\ 261 | \end{center} 262 | \end{frame} 263 | 264 | \note{\scriptsize 265 | \begin{itemize} 266 | \justifying 267 | \item Es gelten die Rechenregeln 268 | \begin{align*} 269 | \texttt{length []} &= \texttt{0}, \\ 270 | \texttt{length (xs ++ ys)} &= \texttt{length xs + length ys} 271 | \end{align*} 272 | für alle Listen~\texttt{xs} und~\texttt{ys}. 273 | Das ist der Grund, wieso die Längenfunktion ein Monoidhomomorphismus ist. 274 | 275 | Achtung: Bevor man eine solche Aussage trifft, muss man eigentlich genauer 276 | spezifizieren, welche Monoidstrukturen man in Quelle und Ziel meint. Auf 277 | dem Typ~\texttt{[a]} soll die Monoidverknüpfung durch Konkatenation gegeben 278 | sein, auf dem Typ~\texttt{Int} durch Addition. 279 | 280 | \item Es gilt die Rechenregel 281 | \begin{equation*} 282 | \texttt{sum (xs ++ ys) = sum xs + sum ys} 283 | \end{equation*} 284 | für alle Listen~\texttt{xs} und~\texttt{ys} von Ints. 285 | Das ist die halbe Miete zur Begründung, wieso~\texttt{sum} ein 286 | Monoidhomomorphismus ist. 287 | 288 | \item Die Rechenregel 289 | \begin{equation*} 290 | \texttt{reverse (xs ++ ys) = reverse xs ++ reverse ys}. 291 | \end{equation*} 292 | gilt \emph{nicht} für alle Listen~\texttt{xs} und~\texttt{ys}. Daher 293 | ist~\texttt{reverse} kein Monoidhomomorphismus. 294 | \end{itemize} 295 | } 296 | 297 | \subsection{Nutzen} 298 | 299 | \begin{frame}\frametitle{Wozu?} 300 | \begin{itemize} 301 | \item Allgegenwärtigkeit 302 | \item Gemeinsamkeiten und Unterschiede 303 | \item Generische Beweise 304 | \item Generische Algorithmen 305 | \end{itemize} 306 | \end{frame} 307 | 308 | \note{ 309 | \begin{itemize} 310 | \item Monoide gibt es überall. 311 | \item Das Monoidkonzept hilft, Gemeinsamkeiten und Unterschiede 312 | zu erkennen und wertschätzen zu können. 313 | \item Man kann generische Beweise für beliebige Monoide führen. 314 | \item Man kann generische Algorithmen mit beliebigen Monoiden basteln. 315 | \end{itemize} 316 | } 317 | 318 | 319 | \subsection{Freie Monoide} 320 | 321 | \begin{frame}\frametitle{Freie Monoide} 322 | Gegeben eine Menge~$X$ ohne weitere Struktur. 323 | Wie können wir auf möglichst unspektakuläre Art und Weise daraus einen 324 | Monoid~$F(X)$ gewinnen? 325 | \medskip 326 | \pause 327 | 328 | Spoiler: Der gesuchte \hil{freie Monoid}~$F(X)$ auf~$X$ ist der Monoid der 329 | endlichen \hil{Listen} mit Elementen aus~$X$. 330 | \medskip 331 | \pause 332 | % auf der Konsole: Erzeuger passen und Relationen passen. 333 | 334 | Essenz der Freiheit: Jede beliebige Abbildung~$X \to M$ in einen Monoid~$M$ 335 | stiftet genau einen Homomorphismus $F(X) \to M$. 336 | \[ \xymatrix{ 337 | X \ar[rr]^{\texttt{phi}} \ar[rd]_{\texttt{inj}} && M \\ 338 | & F(X) \ar@{-->}[ru]_{\texttt{cata phi}} 339 | } \] 340 | \end{frame} 341 | 342 | \note{\justifying 343 | In~$F(X)$ sollen neben den Elementen aus~$X$ gerade nur so viele 344 | weitere Elemente enthalten sein, sodass man eine Verknüpfung~$({\circ})$ und 345 | ein Einselement definieren kann. 346 | Es soll sich also jedes Element aus~$F(X)$ über die Monoidoperationen aus 347 | denen von~$X$ bilden lassen. 348 | \medskip 349 | 350 | In~$F(X)$ sollen nur die Rechenregeln gelten, die von den Monoidaxiomen 351 | gefordert werden. 352 | \medskip 353 | 354 | Die nach "`Essenz der Freiheit"' angegebene Forderung heißt auch 355 | \emph{universelle Eigenschaft}. Präzise formuliert lautet sie wie folgt: 356 | Ein Paar~$(F,\texttt{inj})$ bestehend aus einem Monoid~$F$ und einer 357 | Abbildung~$\texttt{inj} : X \to F$ heißt genau dann \emph{freier Monoid 358 | auf~$X$}, wenn für jedes Paar~$(M,\texttt{phi})$ bestehend aus einem 359 | Monoid~$M$ und einer Abbildung~$\texttt{phi} : X \to M$ genau ein 360 | Monoidhomomorphismus~$\texttt{cata phi} : F \to M$ existiert, 361 | sodass~$\texttt{phi} = \texttt{cata phi} \mathop{.} \texttt{inj}$. 362 | \medskip 363 | 364 | Man kann zeigen -- über ein kategorielles Standardargument -- dass je zwei 365 | Paare~$(F,\texttt{inj})$, welche diese universelle Eigenschaft erfüllen, 366 | vermöge eines eindeutigen Isomorphismus zueinander isomorph sind. Das 367 | rechtfertigt, von \emph{dem} freien Monoid über~$X$ zu sprechen. 368 | \par 369 | } 370 | 371 | \note{\justifying 372 | Man kann die universelle Eigenschaft schön in Haskell demonstrieren: 373 | \inputminted{haskell}{images/universal-property-free-monoid.hs} 374 | 375 | Ist~\texttt{phi} irgendeine Abbildung~\texttt{a -> m}, so ist~\texttt{cata 376 | phi} eine Abbildung~\texttt{[a] -> m}. Diese ist nicht nur irgendeine 377 | Abbildung, sondern wie gefordert ein Monoidhomomorphismus. 378 | \medskip 379 | 380 | Und mehr noch: 381 | Das Diagramm kommutiert tatsächlich, das heißt~\texttt{cata phi} 382 | und~\texttt{phi} haben in folgendem präzisen Sinn etwas miteinander zu 383 | tun: \texttt{cata phi . inj = phi}. Dabei ist~\texttt{inj :: a -> [a]} die 384 | Abbildung mit~\texttt{inj x = [x]}. 385 | \par 386 | } 387 | 388 | \note{\justifying 389 | Unsere Definition von "`unspektakulär"' soll sein: Alle Elemente in~$F(X)$ 390 | setzen sich mit den Monoidoperationen aus denen aus~$X$ zusammen, und 391 | in~$F(X)$ gelten nur die Rechenregeln, die von den Monoidaxiomen erzwungen 392 | werden, aber keine weiteren. 393 | \medskip 394 | 395 | Das ist bei der Konstruktion von~$F(X)$ als Monoid der endlichen Listen 396 | über~$X$ auch in der Tat der Fall: Jede endliche Liste mit Einträgen aus~$X$ 397 | ergibt sich als wiederholte Verknüpfung (Konkatenation) von Listen der 398 | Form~\texttt{inj x} mit~\texttt{x} aus~$X$. Und willkürliche Rechenregeln 399 | wie~\texttt{[a,b] ++ [b,a] == [c]} gelten, wie es auch sein soll, 400 | \emph{nicht}. 401 | \medskip 402 | 403 | Wieso fängt die universelle Eigenschaft genau diese Definition von 404 | Unspektakularität ein? Wenn man zu~$F(X)$ noch weitere Elemente hinzufügen 405 | würde (zum Beispiel unendliche Listen), so wird es mehrere oder keinen 406 | Kandidaten für~\texttt{cata phi} geben, aber nicht mehr nur einen. Genauso 407 | wenn man in~$F(X)$ durch Identifikation gewisser Elemente weitere 408 | Rechenregeln erzwingen würde. 409 | \par 410 | } 411 | 412 | \note{\justifying 413 | Wenn man tiefer in das Thema einsteigt, erkennt man, dass endliche Listen 414 | noch nicht der Weisheit letzter Schluss sind: 415 | \url{http://comonad.com/reader/2015/free-monoids-in-haskell/} 416 | \medskip 417 | 418 | Kurz zusammengefasst: Es stimmt schon, dass der Monoid der endlichen Listen 419 | über~$X$ der freie Monoid auf~$X$ ist, sofern man als Basiskategorie in der 420 | Kategorie der Mengen arbeitet. Wenn man dagegen in~$\Hask$ arbeitet, der 421 | Kategorie der Haskell-Typen und -Funktionen, so benötigt man eine leicht 422 | andere Konstruktion. 423 | \medskip 424 | 425 | Fun Fact: Die in dem Blog-Artikel angegebene Konstruktion ergibt sich 426 | \emph{unmittelbar} aus der universellen Eigenschaft. Es ist keine Überlegung 427 | und manuelle Suche nach einem geeigneten Kandidaten für~$F(X)$ nötig. 428 | (Bemerkung für Kategorientheorie-Fans: Das es so einfach geht, liegt an einer 429 | gewissen Vollständigkeitseigenschaft von~$\Hask$.) 430 | \par 431 | } 432 | 433 | \begin{frame}\frametitle{Freie Monoide} 434 | \begin{center}\Large 435 | Freie Monoide sind \ldots 436 | 437 | \only<1>{\ldots{} frei wie in Freibier?}% 438 | \only<2->{\hcancel{\ldots{} frei wie in Freibier?}{0pt}{3pt}{0pt}{-2pt}} 439 | 440 | \only<3>{\ldots{} frei wie in Redefreiheit?}% 441 | \only<4->{\hcancel{\ldots{} frei wie in Redefreiheit?}{0pt}{3pt}{0pt}{-2pt}} 442 | 443 | \only<5->{\ldots{} frei wie in \hil{linksadjungiert}! $\checkmark$} 444 | 445 | \end{center} 446 | 447 | \only<6>{Der Funktor~$F : \mathrm{Set} \to \mathrm{Mon}$ ist \hil{linksadjungiert} 448 | zum Vergissfunktor~$\mathrm{Mon} \to \mathrm{Set}$.} 449 | \end{frame} 450 | 451 | \note{\justifying 452 | Für jede algebraische Struktur \emph{Mumble} gibt es das Konzept des 453 | \emph{freien Mumbles über einer Menge}. Beispiele: 454 | \begin{itemize}\justifying 455 | \item Der freie Monoid über~$X$ ist der Monoid der endlichen Listen mit 456 | Einträgen aus~$X$. 457 | \item Der freie abelsche Monoid über~$X$ ist der abelsche Monoid der 458 | endlichen Multimengen von Elementen aus~$X$. 459 | \item Die freie Halbgruppe über~$X$ ist die Halbgruppe der nichtleeren Listen 460 | mit Einträgen aus~$X$. 461 | \item Das freie Magma über~$X$ ist das Magma der binären Bäume mit Elementen 462 | aus~$X$ an den Blättern. 463 | \item Der freie Ring über~$X$ ist der Ring der Polynome mit ganzzahligen 464 | Koeffizienten und den Elementen aus~$X$ als Polynomvariablen. 465 | \end{itemize} 466 | 467 | \scriptsize 468 | Zur Erinnerung: Eine Halbgruppe ist wie ein Monoid, nur, dass es nicht 469 | unbedingt ein neutrales Element geben muss. Ein Magna ist wie eine 470 | Halbgruppe, nur, dass die Verknüpfung nicht assoziativ sein muss. Ein Ring 471 | ist wie ein Körper, nur dass man keinerlei multiplikative Inverse fordert. 472 | \par 473 | } 474 | 475 | \section{Funktoren} 476 | 477 | \subsection{Definition und Beispiele} 478 | 479 | \begin{frame}[fragile]\frametitle{Funktoren} 480 | Ein \hil{Funktor}~$F : \C \to \D$ zwischen Kategorien~$\C$ und~$\D$ ordnet 481 | \begin{itemize} 482 | \item jedem Objekt~$X \in \C$ ein Objekt~$F(X) \in \D$ und 483 | \item jedem Morphismus~$f : X \to Y$ in~$\C$ ein Morphismus~$F(f) : F(X) 484 | \to F(Y)$ in~$\D$ zu, 485 | \end{itemize} 486 | sodass die \hil{Funktoraxiome} erfüllt sind: 487 | \begin{itemize} 488 | \item $F(\id_X) = \id_{F(X)}$, 489 | \item $F(g \circ f) = F(g) \circ F(f)$. 490 | \end{itemize} 491 | \vfill 492 | 493 | In Haskell kommen Funktoren~$\Hask \to \Hask$ vor: 494 | \begin{minted}{haskell} 495 | class Functor f where 496 | fmap :: (a -> b) -> (f a -> f b) 497 | -- fmap id = id 498 | -- fmap (g . f) = fmap g . fmap f 499 | \end{minted} 500 | \end{frame} 501 | 502 | \note{\justifying 503 | Fun Fact am Rande: Ein Theorem für lau garantiert, dass in Haskell das zweite 504 | Funktoraxiom aus dem ersten folgt. 505 | \par 506 | } 507 | 508 | \begin{frame}[fragile]\frametitle{Beispiele für Funktoren} 509 | \vspace*{-1em} 510 | \small 511 | \begin{minted}{haskell} 512 | class Functor f where 513 | fmap :: (a -> b) -> (f a -> f b) 514 | 515 | instance Functor [] where fmap f = map f 516 | 517 | data Maybe a = Nothing | Just a 518 | instance Functor Maybe where 519 | fmap f Nothing = Nothing 520 | fmap f (Just x) = Just (f x) 521 | 522 | data Id a = MkId a 523 | instance Functor Id where 524 | fmap f (MkId x) = MkId (f x) 525 | 526 | data Pair a = MkPair a a 527 | instance Functor Pair where 528 | fmap f (MkPair x y) = MkPair (f x) (f y) 529 | \end{minted} 530 | \end{frame} 531 | 532 | 533 | \subsection{Funktoren als Container} 534 | 535 | \begin{frame}[fragile]\frametitle{Funktoren als Container} 536 | Ist~\texttt{f} ein Funktor, so stellen wir uns den 537 | Typ~\texttt{f a} als einen Typ von Containern von Werten vom 538 | Typ~\texttt{a} vor. 539 | \medskip 540 | 541 | Je nach Funktor haben die Container eine andere Form. 542 | 543 | \vfill 544 | \begin{minted}{haskell} 545 | class Functor f where 546 | fmap :: (a -> b) -> (f a -> f b) 547 | 548 | data List a = Nil | Cons a [a] 549 | data Maybe a = Nothing | Just a 550 | data Id a = MkId a 551 | data Pair a = MkPair a a 552 | data Unit a = MkUnit 553 | data Void a 554 | \end{minted} 555 | \end{frame} 556 | 557 | \note{\justifying 558 | Die Vorstellung ist aus folgendem Grund plausibel: Aus einer 559 | Funktion~\texttt{a -> b} können wir mit \texttt{fmap} eine Funktion~\texttt{f 560 | a -> f b} machen. Also stecken wohl in einem Wert vom Typ~\texttt{f a} 561 | irgendwelche Werte vom Typ~\texttt{a}, die mit der gelifteten Funktion dann 562 | in Werte vom Typ~\texttt{b} umgewandelt werden. 563 | \par 564 | } 565 | 566 | 567 | \section{Monaden} 568 | 569 | \subsection{Definition und Beispiele} 570 | 571 | \note{\justifying 572 | Im Folgenden ist~$\Hask$ eine geeignete Kategorie von Haskell-Typen und 573 | -Funktionen. Die Objekte sollen also Haskell-Typen sein, und Morphismen 574 | zwischen je zwei Typen sollen durch Haskell-Funktionen des entsprechenden 575 | Typs gegeben sein. 576 | \medskip 577 | 578 | Die Kategorie~$\mathrm{End}(\Hask)$ ist die Kategorie der 579 | \emph{Endofunktoren} von~$\Hask$. Deren Objekte sind Funktoren~$\Hask \to 580 | \Hask$ (also das, was man in Haskell gewöhnlich als "`Funktor"' bezeichnet) 581 | und deren Morphismen sind natürliche Transformationen (siehe übernächste 582 | Folie). 583 | \par 584 | } 585 | 586 | \begin{frame}\frametitle{Monoidale Kategorien} 587 | \small 588 | \begin{tabular}{@{}ll@{}} 589 | \toprule 590 | $\mathrm{Set}$ & $\mathrm{End}(\Hask)$ \\\midrule 591 | Menge $M$ & Funktor $M$ \\ 592 | Abbildung $M \to N$ & natürliche Transformation $\forall a. M a \to N a$ \\ 593 | $M \times N$ & $M \circ N$ mit $(M \circ N) a = M (N a)$ \\ 594 | nur linke Komponente ändern & nur äußere Schicht ändern \\ 595 | nur rechte Komponente ändern & nur innere Schicht ändern \\ 596 | \pause 597 | \hil{Monoid} & \hil{Monade} \\ 598 | \bottomrule 599 | \end{tabular} 600 | 601 | \begin{center} 602 | \includegraphics[height=3.3cm]{images/a-monad-is-just-4} 603 | \qquad 604 | \includegraphics[height=3.3cm]{images/a-monad-is-just-5} 605 | \end{center} 606 | \end{frame} 607 | 608 | \note{\justifying 609 | In der Kategorientheorie ist eine natürliche Transformation~$\eta : F 610 | \Rightarrow G$ zwischen zwei Funktoren~$F, G : \C \to \D$ eine Familie von 611 | Morphismen~$\eta_X : F(X) \to G(X)$ (ein Morphismus für jedes Objekt~$X \in 612 | \C$), sodass für jeden Morphismus~$f : X \to Y$ in~$\C$ das Diagramm 613 | \[ \xymatrix{ 614 | F(X) \ar[r]^{\eta_X} \ar[d]_{F(f)} & G(X) \ar[d]^{G(f)} \\ 615 | F(Y) \ar[r]_{\eta_Y} & G(Y) 616 | } \] 617 | kommutiert.\par 618 | } 619 | 620 | \note{\justifying 621 | Spezialisiert auf den Spezialfall~$\C = \D = \Hask$ [und ein externes Hom in 622 | ein internes verwandelt, was auch immer das heißt] ist eine natürliche 623 | Transformation~$\texttt{eta} : F \Rightarrow G$ eine polymorphe 624 | Haskell-Funktion 625 | \begin{center}\inputminted{haskell}{images/natural-transformation.hs}\end{center} 626 | mit 627 | \begin{center}\inputminted{haskell}{images/natural-transformation-law.hs}\end{center} 628 | für alle Funktionen~\texttt{f :: a -> b}. 629 | \medskip 630 | 631 | Ein Theorem für lau garantiert aber, dass jede Funktion~\texttt{eta} des 632 | richtigen Typs automatisch diese Kompatibilitätsbedingung mit dem 633 | \texttt{fmap} von~\texttt{F} bzw. dem von~\texttt{G} erfüllt, weswegen man 634 | diese Bedingung nicht explizit fordern muss. (Vereinfacht gesprochen liegt 635 | der Grund dafür darin, dass eine Haskell-Funktion nicht in Abhängigkeit der 636 | konkreten Instanz der Typvariablen~\texttt{a} ihr Verhalten ändern kann.) 637 | \par 638 | } 639 | 640 | \note{\justifying 641 | Beispiele für natürliche Transformationen gibt es in Haskell viele: 642 | \begin{itemize}\justifying 643 | \item \texttt{maybeToList :: Maybe a -> [a]} 644 | 645 | \item \texttt{eitherToMaybe :: Either E a -> Maybe a} 646 | 647 | Dabei ist \texttt{E} ein bestimmter fester Typ. 648 | 649 | \item \texttt{listToMaybe :: [a] -> Maybe a} 650 | 651 | Dieses Beispiel zeigt, dass natürliche Transformationen durchaus 652 | Informationen vernichten dürfen. 653 | 654 | \item \texttt{sequence :: [M a] -> M [a]} 655 | 656 | Dabei ist \texttt{M} eine bestimmte feste Monade. 657 | 658 | \item \texttt{tail :: [a] -> [a]} 659 | 660 | \item \texttt{length :: [a] -> Int} 661 | 662 | Dabei steht auf der rechten Seite die Anwendung von \texttt{a} auf den 663 | \emph{konstanten Funktor bei \texttt{Int}}. 664 | \end{itemize} 665 | } 666 | 667 | \note{\justifying 668 | Die Kategorien~$\mathrm{Set}$ und~$\mathrm{End}(\Hask)$ können beide mit 669 | einer \emph{monoidalen Struktur} versehen werden. In der Kategorie der Mengen 670 | ist das die Operation~$(M,N) \mapsto M \times N$. In der Kategorie der 671 | Endofunktoren von~$\Hask$ ist es~$(M,N) \mapsto M \circ N$. 672 | \medskip 673 | 674 | In jeder monoidalen Kategorie (also einer Kategorie zusammen mit einer 675 | monoidalen Struktur) kann man von \emph{Monoid-Objekten} sprechen. 676 | Monoid-Objekte in~$\mathrm{Set}$ sind einfach ganz gewöhnliche Monoide. 677 | Monoid-Objekte in~$\mathrm{End}(\Hask)$ sind Monaden. 678 | \medskip 679 | 680 | Siehe auch: \\ 681 | \url{http://blog.sigfpe.com/2008/11/from-monoids-to-monads.html}. 682 | \par 683 | } 684 | 685 | \begin{frame}[fragile]\frametitle{Monaden} 686 | Eine \hil{Monade} besteht aus 687 | \begin{itemize} 688 | \item einem Funktor~$M$, 689 | \item einer natürlichen Transformation~$M \circ M \Rightarrow M$ und 690 | \item einer natürlichen Transformation~$\Id \Rightarrow M$, 691 | \end{itemize} 692 | sodass die \hil{Monadenaxiome} gelten. 693 | \pause 694 | 695 | \begin{minted}{haskell} 696 | class (Functor m) => Monad m where 697 | join :: m (m a) -> m a 698 | return :: a -> m a 699 | \end{minted} 700 | 701 | \begin{columns} 702 | \begin{column}{0.38\textwidth} 703 | \begin{block}{Listen} 704 | \scriptsize 705 | \begin{minted}{haskell} 706 | concat :: [[a]] -> [a] 707 | singleton :: a -> [a] 708 | \end{minted} 709 | \end{block} 710 | \end{column} 711 | \begin{column}{0.50\textwidth} 712 | \begin{block}{Maybe} 713 | \scriptsize 714 | \begin{minted}{haskell} 715 | join :: Maybe (Maybe a) -> Maybe a 716 | Just :: a -> Maybe a 717 | \end{minted} 718 | \end{block} 719 | \end{column} 720 | \end{columns} 721 | \end{frame} 722 | 723 | \note{\justifying 724 | Anschauliche Interpretation: Monaden sind spezielle Containertypen, die zwei 725 | Zusatzfähigkeiten haben: Ein Container von Containern von Werten soll man zu 726 | einem einfachen Container von Werten "`flatten"' können (\texttt{join}), und 727 | einen einzelnen Wert soll man in einen Container packen können 728 | (\texttt{return}). 729 | \par 730 | } 731 | 732 | \begin{frame}[fragile]\frametitle{Weitere Beispiele} 733 | \vspace*{-1em} 734 | \begin{minted}{haskell} 735 | class (Functor m) => Monad m where 736 | join :: m (m a) -> m a 737 | return :: a -> m a 738 | \end{minted} 739 | 740 | \begin{block}{Reader} 741 | \scriptsize 742 | \begin{minted}{haskell} 743 | type Reader env a = env -> a 744 | 745 | instance Functor (Reader env) where 746 | fmap f k = f . k 747 | 748 | instance Monad (Reader env) where 749 | return x = \_ -> x 750 | join k = \env -> k env env 751 | \end{minted} 752 | \end{block} 753 | 754 | \begin{block}{State} 755 | \scriptsize 756 | \begin{minted}{haskell} 757 | type State s a = s -> (a,s) 758 | 759 | instance Monad (State s) where 760 | return x = \s -> (x,s) 761 | join k = \s -> let (k',s') = k s in k' s' 762 | \end{minted} 763 | \end{block} 764 | \end{frame} 765 | 766 | \note{\justifying 767 | Auch \texttt{State s} und \texttt{Reader env} passen in die "`Container mit 768 | Zusatzfähigkeit"'-Intuition, wenn man sich hinreichend verbiegt. Schaffst du 769 | das? 770 | \par 771 | } 772 | 773 | 774 | \subsection[Slogan]{"`Monoid in einer Kategorie von Endofunktoren"'} 775 | 776 | \begin{frame}\frametitle{Die Monadenaxiome} 777 | {\scriptsize 778 | Sprechweise: Ein Wert vom Typ~\texttt{m (m (m a))} ist ein (äußerer) Container von 779 | (inneren) Containern von (ganz inneren) Containern von Werten vom 780 | Typ~\texttt{a}.\par} 781 | 782 | \[ \xymatrixcolsep{4pc}\xymatrixrowsep{4pc}\xymatrix{ 783 | M \circ M \circ M \ar@{=>}[r]^{\text{innen join}} \ar@{=>}[d]_{\text{außen join}} & M \circ M 784 | \ar@{=>}[d]^{\text{join}} \\ 785 | M \circ M \ar@{=>}[r]_{\text{join}} & M 786 | } \] 787 | \medskip 788 | \[ \xymatrixcolsep{4pc}\xymatrixrowsep{4pc}\xymatrix{ 789 | & M \\ 790 | M \ar@{=>}[r]_{\text{return}}\ar@{=>}[ru] & M \circ M \ar@{=>}[u]_{\text{join}} & \ar@{=>}[l]^{\text{innen 791 | return}}\ar@{=>}[lu] M 792 | } \] 793 | \end{frame} 794 | 795 | % Mündlich: Das Motto rezipieren. 796 | 797 | 798 | \section{Freie Monaden} 799 | 800 | \subsection{Definition} 801 | 802 | \begin{frame}[fragile]\frametitle{Freie Monaden} 803 | Gegeben ein Funktor~\texttt{f} ohne weitere Struktur. Wie können wir auf 804 | möglichst ökonomische Art und Weise daraus eine 805 | Monade~\mintinline{haskell}{Free f} konstruieren? 806 | \[ \xymatrix{ 807 | F \ar@{=>}[rr] \ar@{=>}[rd] && M \\ 808 | & \operatorname{Free} F \ar@{==>}[ru] 809 | } \] 810 | \begin{minted}{haskell} 811 | can :: (Functor f, Monad m) 812 | => (forall a. f a -> m a) 813 | -> (forall a. Free f a -> m a) 814 | \end{minted} 815 | \end{frame} 816 | 817 | 818 | \subsection{Konstruktion} 819 | 820 | \note{ 821 | \scriptsize 822 | \inputminted{haskell}{images/definition-free-monad.hs} 823 | } 824 | 825 | \note{\justifying 826 | \texttt{Free f a} ist der Typ der "`\texttt{f}-förmigen"' Bäume mit Blättern 827 | vom Typ~\texttt{a}. Dabei flattened \texttt{join} einen~\texttt{f}-förmigen 828 | Baum von~\texttt{f}-förmigen Bäumen von irgendwelchen Werten zu einem 829 | einfachen~\texttt{f}-förmigen Baum dieser Werte. 830 | 831 | \begin{itemize}\justifying 832 | \item \texttt{Free Void} ist die \texttt{Id}-Monade. 833 | \item \texttt{Free Unit} ist die \texttt{Maybe}-Monade. Hier hat jeder 834 | Mutterknoten kein einziges Kind. Die Bezeichnung "`Mutterknoten"' ist also 835 | etwas euphemistisch. 836 | \item \texttt{Free Pair} ist die \texttt{Tree}-Monade. Hier hat jeder 837 | Mutterknoten genau zwei Kinder. 838 | \item \texttt{Free Id} ist die \texttt{(Writer Nat)}-Monade. Hier hat 839 | jeder Mutterknoten genau ein Kind. 840 | \end{itemize} 841 | 842 | Die Listen-Monade ist übrigens nicht frei. Übungsaufgabe: Beweise das! 843 | \par 844 | } 845 | 846 | 847 | \subsection{Nutzen} 848 | 849 | \begin{frame}\frametitle{Anwendungen freier Monaden} 850 | \begin{itemize}\justifying 851 | \item Viele wichtige Monaden sind frei. 852 | \item Freie Monaden kapseln das "`Interpreter-Muster"'. 853 | \item Freie Monaden können zur Konstruktion weiterer Monaden genutzt 854 | werden, etwa zum Koprodukt zweier Monaden, welches die Fähigkeiten zweier 855 | gegebener Monaden vereint. 856 | \end{itemize} 857 | \end{frame} 858 | 859 | \note{\justifying 860 | Die in diesen Folien gegebene Konstruktion der freien Monade hat ein 861 | Effizienzproblem -- genau wie bei der linksgeklammerten Verkettung von 862 | Listen. Mit der sog. Kodichtemonade, einer speziellen Links-Kan-Erweiterung, 863 | kann man das Problem lösen. 864 | \medskip 865 | 866 | Mehr zum Interpreter-Muster gibt es in einem Folgevortrag zu Effektsystemen. 867 | Kurz zusammengefasst: Wenn man maßgeschneidert eine Monade konstruieren 868 | möchte, welche genau einen gewissen Satz von Nebenwirkungen unterstützt, dann 869 | kann man das über freie Monaden. Und noch einfacher über "`freiere 870 | Monaden"' (da ist der Ausgangspunkt nur ein Typkonstruktor~\texttt{F}, der 871 | \emph{kein} Funktor sein muss). 872 | \medskip 873 | 874 | Ein Vorgeschmack in Form von Haskell-Code gibt es unter 875 | \url{https://github.com/iblech/vortrag-haskell/blob/master/freie-monaden.hs}. 876 | \par 877 | } 878 | 879 | \backupstart 880 | \begin{frame}[plain] 881 | \begin{center} 882 | \includegraphics[scale=0.55]{images/a-monad-is-just-2} 883 | \end{center} 884 | 885 | \small\justifying 886 | Nach der Schule trifft Barbie Paul und Peter in der Bibliothek. "`Funktionale 887 | Programmierung ist fantastisch!"', freut sich Barbie. "`Ich weiß nicht", sagt 888 | Paul, "`was zum Teufel ist eine Monade noch mal?"'. "`Eine Monade ist einfach 889 | ein Monoid in einer Kategorie von Endofunktoren -- wo liegt das Problem?"', 890 | antwortet Barbie. 891 | \par 892 | \end{frame} 893 | \backupend 894 | 895 | \end{document} 896 | 897 | Monoide 898 | * Definition und Beispiele 899 | * Nutzen: Gemeinsamkeiten, generische Algorithmen, ... 900 | * Freie Monoide: Ökonomieprinzip, universelle Eigenschaft 901 | 902 | Funktoren als Container 903 | 904 | Monaden 905 | * Monaden als Container, die eine Art "join" unterstützen 906 | * Monadenaxiome (mit Gegenüberstellung Set vs. End(Hask)) 907 | 908 | Freie Monaden 909 | * Herleitung/Definition 910 | * Universelle Eigenschaft 911 | * Beispiel: Interpreter-Muster; State, Writer, Reader; State als Summe von Writer und Reader 912 | * Ausblick: Performanceprobleme 913 | -------------------------------------------------------------------------------- /freie-monaden.txt: -------------------------------------------------------------------------------- 1 | Sei X die Menge { a, b, c }. 2 | 3 | Im freien Monoid über X sind dann enthalten: 4 | ^ 5 | \ 6 | \ 7 | +--------- Monoid der endlichen Listen über X, 8 | also nicht ganz [X] in Haskell 9 | 10 | [ a, b, b, b, a ] -- a b b b a 11 | [ ] 12 | 13 | In der freien Gruppe über X sind dann enthalten: 14 | 15 | a b b b a 16 | a^(-1) b a b 17 | a a^(-1) b a b = b a b 18 | 19 | type FreeGroup x = [Either x x] 20 | = [(x, Bool)] (aber jeweils nur mit 21 | sozialem Vertrag mit 22 | dem Programmier) 23 | 24 | [ (a, False), (a, True), (b, False) ] /= [ (b,False) ] 25 | Diese beide Elemente sind in den beiden Listenmodellen nicht gleich. 26 | In FreeGroup x sollten sie es aber sein. 27 | 28 | In der freien abelschen Gruppe über X sind enthalten: 29 | 30 | a b b b a = a a b b b 31 | a^(-1) b a^(-1) a = a^(-1) a^(-1) a b = a^(-1) b 32 | -- will man im freien Objekt nicht haben: a b b = b 33 | -- nicht im freien Objekt enthalten: a b c d e f g ... 34 | 35 | type FreeAbelianGroup x = der Untertyp von (x -> Integer), 36 | wo die Funktionen nur auf 37 | endlich vielen Elementen 38 | nicht Null sind. 39 | -- Achtung! Diese Definition funktioniert nicht in 40 | -- konstruktiver Mathematik. 41 | 42 | 43 | 44 | Beispiele für natürliche Trafos: 45 | 46 | maybeToList :: Maybe a -> [a] 47 | maybeToList Nothing = [] 48 | maybeToList (Just x) = [x] 49 | 50 | eitherToMaybe :: Either e a -> Maybe a 51 | 52 | listToMaybe :: [a] -> Maybe a 53 | listToMaybe [] = Nothing 54 | listToMaybe (x:_) = Just x 55 | 56 | sequence :: [IO a] -> IO [a] 57 | 58 | 59 | 60 | Ein eta :: F a -> G a heißt in der Kategorientheorie 61 | genau dann natürliche Trafo, wenn gilt: 62 | 63 | fmap f . eta = eta . fmap f 64 | 65 | für alle f :: a -> b. 66 | 67 | 68 | 69 | (List o Maybe) a = [Maybe a] 70 | hier: äußere Schicht: Liste von Sachen 71 | innere Schicht: viele Maybes 72 | 73 | (Maybe o List) a = Maybe [a] 74 | (IO . List) a = IO [a] 75 | (List . IO) a = [IO a] 76 | 77 | 78 | 79 | 80 | Sei f : M --> M'. 81 | Diese Abbildung induziert eine Abbildung 82 | 83 | first f : M x N ---> M' x N 84 | (x,y) |--> (f(x),y) 85 | 86 | Das meinen wir mit "nur linke Komponente ändern". 87 | 88 | 89 | 90 | Sei g : N --> N'. 91 | Diese Abbildung induziert eine Abbildung 92 | 93 | second g : M x N ---> M x N' 94 | (x,y) |--> (x,g(y)) 95 | 96 | Das meinen wir mit "nur rechte Komponente ändern". 97 | 98 | 99 | 100 | F o G 101 | f :: F a --> F' a 102 | Das induziert: 103 | 104 | F (G a) --> F' (G a) 105 | x |-> f x 106 | 107 | Das meinen wir mit "nur äußere Schicht ändern". 108 | 109 | 110 | 111 | g :: G a --> G' a 112 | Das induziert: 113 | 114 | F (G a) --> F (G' a) 115 | x |-> fmap g x 116 | 117 | Das meinen wir mit "nur innere Schicht ändern". 118 | 119 | 120 | 121 | Ein Element einer Menge X 122 | ist "dasselbe" wie eine Abbildung 123 | 124 | E = { * } --> X 125 | 126 | Das Besondere an E: 127 | X x E ~~ X 128 | (x,*) |-> x 129 | (x,*) <-| x 130 | 131 | 132 | In der Kategorie End(Hask) statt Set nimmt die Rolle von E der 133 | Identitätsfunktor ein, denn: 134 | F o Id = F 135 | Id o F = F 136 | 137 | 138 | 139 | 140 | data Pair a = MkPair a a 141 | = Bool -> a 142 | = Reader Bool a 143 | 144 | 145 | -- Folgende Definition erfüllt nicht die Monadenaxiome: 146 | return :: a -> Pair a 147 | return x = MkPair x x 148 | 149 | join :: Pair (Pair a) -> Pair a 150 | join (MkPair (MkPair x y) (MkPair x' y')) 151 | = MkPair x x' 152 | 153 | -- Aber folgende schon. 154 | join (MkPair (MkPair x y) (MkPair x' y')) 155 | = MkPair x y' 156 | 157 | 158 | 159 | 160 | Richi redet vom Monoid der Teilmengen von X: 161 | neutrales Element: {} 162 | Komposition: M o N = M cup N 163 | 164 | 165 | 166 | module Main where 167 | 168 | data Free f a 169 | = Pure a 170 | | Roll (f (Free f a)) 171 | -- Free f a ist der Typ der "f-förmigen" Bäume (mit Werte nur an den Blättern). 172 | 173 | -- Free f a ist ein Datentyp, d.h. vom Kind *. 174 | -- Free f ist vom Kind * -> *. 175 | -- Free ist vom Kind (* -> *) -> (* -> *). 176 | -- Für einen gegebenen Funktor f ist Free f ein neuer Funktor. Und sogar eine 177 | -- Monade. 178 | 179 | -- In GADT-Schreibweise: 180 | data Free :: (* -> *) -> (* -> *) where 181 | Pure :: a -> Free f a 182 | Roll :: f (Free f a) -> Free f a 183 | 184 | 185 | -- Beispiele! 186 | data Unit a = MkUnit 187 | instance Functor Unit where 188 | fmap f MkUnit = MkUnit 189 | 190 | -- Was ist Free Unit? 191 | -- Genauer: Was ist Free Unit a? 192 | -- Antwort: Maybe! Free Unit a = Maybe a 193 | 194 | data Maybe a = Just a | Nothing 195 | iso :: Maybe a -> Free Unit a 196 | iso (Just x) = Pure x 197 | iso Nothing = Roll MkUnit 198 | 199 | 200 | -- Noch ein Beispiel! 201 | data Pair a = MkPair a a 202 | -- Free Pair ist der Typ der Binärbäume: 203 | -- data Tree a = Leaf a | Fork (Tree a) (Tree a) 204 | -- Dann gilt: Free Pair a = Tree a. 205 | 206 | -- Was ist Free Id? 207 | -- Mögliche Werte in Free Id sind: 208 | -- Pure 7, Roll (Pure 7), Roll (Roll (Pure 7)), Roll (Roll (Roll (Pure 7))) 209 | -- Also: Free Id a = (Nat,a) = Writer Nat a. 210 | 211 | 212 | -- Es gibt jeweils nur eine mögliche Definition, die den richtigen Typ hat. 213 | instance (Functor f) => Functor (Free f) where ... 214 | instance (Functor f) => Monad (Free f) where ... 215 | -------------------------------------------------------------------------------- /images/a-monad-is-just-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/a-monad-is-just-1.jpeg -------------------------------------------------------------------------------- /images/a-monad-is-just-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/a-monad-is-just-2.png -------------------------------------------------------------------------------- /images/a-monad-is-just-3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/a-monad-is-just-3.jpeg -------------------------------------------------------------------------------- /images/a-monad-is-just-4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/a-monad-is-just-4.jpeg -------------------------------------------------------------------------------- /images/a-monad-is-just-5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/a-monad-is-just-5.jpeg -------------------------------------------------------------------------------- /images/baum.fig: -------------------------------------------------------------------------------- 1 | #FIG 3.2 Produced by xfig version 3.2.5 2 | Landscape 3 | Center 4 | Metric 5 | A4 6 | 100.00 7 | Single 8 | -2 9 | 1200 2 10 | 6 1860 1882 4194 2062 11 | 4 0 0 50 -1 0 12 0.0000 14 180 480 1860 2032 $17$\001 12 | 4 0 0 50 -1 0 12 0.0000 14 180 480 2805 2032 $37$\001 13 | 4 0 0 50 -1 0 12 0.0000 14 180 480 4170 2032 $41$\001 14 | -6 15 | 6 3000 2782 3579 2962 16 | 4 0 0 50 -1 0 12 0.0000 14 180 480 3000 2932 $42$\001 17 | 4 0 0 50 -1 0 12 0.0000 14 180 360 3555 2932 $0$\001 18 | -6 19 | 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 3150 450 90 90 3150 450 3240 450 20 | 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 2475 900 90 90 2475 900 2565 900 21 | 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 3825 900 90 90 3825 900 3915 900 22 | 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 3375 1800 90 90 3375 1800 3465 1800 23 | 2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2 24 | 3375 1800 3600 2700 25 | 2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2 26 | 3375 1800 3150 2700 27 | 2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2 28 | 3825 900 3375 1800 29 | 2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2 30 | 3825 900 4275 1800 31 | 2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2 32 | 3150 450 3825 900 33 | 2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2 34 | 3150 450 2475 900 35 | 2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2 36 | 2475 900 2925 1800 37 | 2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2 38 | 2475 900 2025 1800 39 | -------------------------------------------------------------------------------- /images/baum.pspdftex: -------------------------------------------------------------------------------- 1 | \begin{picture}(0,0)% 2 | \includegraphics{images/baum_pspdftex}% 3 | \end{picture}% 4 | \setlength{\unitlength}{4144sp}% 5 | % 6 | \begingroup\makeatletter\ifx\SetFigFont\undefined% 7 | \gdef\SetFigFont#1#2#3#4#5{% 8 | \reset@font\fontsize{#1}{#2pt}% 9 | \fontfamily{#3}\fontseries{#4}\fontshape{#5}% 10 | \selectfont}% 11 | \fi\endgroup% 12 | \begin{picture}(2452,2648)(1846,-2162) 13 | \put(1861,-1193){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$17$}% 14 | }}}} 15 | \put(2806,-1193){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$37$}% 16 | }}}} 17 | \put(4171,-1193){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$41$}% 18 | }}}} 19 | \put(3001,-2093){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$42$}% 20 | }}}} 21 | \put(3556,-2093){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$0$}% 22 | }}}} 23 | \end{picture}% 24 | -------------------------------------------------------------------------------- /images/baum_pspdftex.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-2.0 EPSF-2.0 2 | %%Title: baum.pstex 3 | %%Creator: fig2dev Version 3.2 Patchlevel 5 4 | %%CreationDate: Fri Mar 19 09:31:24 2010 5 | %%For: iblech@thestars (Ingo Blechschmidt) 6 | %%BoundingBox: 0 0 155 167 7 | %Magnification: 1.0000 8 | %%EndComments 9 | /$F2psDict 200 dict def 10 | $F2psDict begin 11 | $F2psDict /mtrx matrix put 12 | /col-1 {0 setgray} bind def 13 | /col0 {0.000 0.000 0.000 srgb} bind def 14 | /col1 {0.000 0.000 1.000 srgb} bind def 15 | /col2 {0.000 1.000 0.000 srgb} bind def 16 | /col3 {0.000 1.000 1.000 srgb} bind def 17 | /col4 {1.000 0.000 0.000 srgb} bind def 18 | /col5 {1.000 0.000 1.000 srgb} bind def 19 | /col6 {1.000 1.000 0.000 srgb} bind def 20 | /col7 {1.000 1.000 1.000 srgb} bind def 21 | /col8 {0.000 0.000 0.560 srgb} bind def 22 | /col9 {0.000 0.000 0.690 srgb} bind def 23 | /col10 {0.000 0.000 0.820 srgb} bind def 24 | /col11 {0.530 0.810 1.000 srgb} bind def 25 | /col12 {0.000 0.560 0.000 srgb} bind def 26 | /col13 {0.000 0.690 0.000 srgb} bind def 27 | /col14 {0.000 0.820 0.000 srgb} bind def 28 | /col15 {0.000 0.560 0.560 srgb} bind def 29 | /col16 {0.000 0.690 0.690 srgb} bind def 30 | /col17 {0.000 0.820 0.820 srgb} bind def 31 | /col18 {0.560 0.000 0.000 srgb} bind def 32 | /col19 {0.690 0.000 0.000 srgb} bind def 33 | /col20 {0.820 0.000 0.000 srgb} bind def 34 | /col21 {0.560 0.000 0.560 srgb} bind def 35 | /col22 {0.690 0.000 0.690 srgb} bind def 36 | /col23 {0.820 0.000 0.820 srgb} bind def 37 | /col24 {0.500 0.190 0.000 srgb} bind def 38 | /col25 {0.630 0.250 0.000 srgb} bind def 39 | /col26 {0.750 0.380 0.000 srgb} bind def 40 | /col27 {1.000 0.500 0.500 srgb} bind def 41 | /col28 {1.000 0.630 0.630 srgb} bind def 42 | /col29 {1.000 0.750 0.750 srgb} bind def 43 | /col30 {1.000 0.880 0.880 srgb} bind def 44 | /col31 {1.000 0.840 0.000 srgb} bind def 45 | 46 | end 47 | save 48 | newpath 0 167 moveto 0 0 lineto 155 0 lineto 155 167 lineto closepath clip newpath 49 | -116.2 189.0 translate 50 | 1 -1 scale 51 | 52 | /cp {closepath} bind def 53 | /ef {eofill} bind def 54 | /gr {grestore} bind def 55 | /gs {gsave} bind def 56 | /sa {save} bind def 57 | /rs {restore} bind def 58 | /l {lineto} bind def 59 | /m {moveto} bind def 60 | /rm {rmoveto} bind def 61 | /n {newpath} bind def 62 | /s {stroke} bind def 63 | /sh {show} bind def 64 | /slc {setlinecap} bind def 65 | /slj {setlinejoin} bind def 66 | /slw {setlinewidth} bind def 67 | /srgb {setrgbcolor} bind def 68 | /rot {rotate} bind def 69 | /sc {scale} bind def 70 | /sd {setdash} bind def 71 | /ff {findfont} bind def 72 | /sf {setfont} bind def 73 | /scf {scalefont} bind def 74 | /sw {stringwidth} bind def 75 | /tr {translate} bind def 76 | /tnt {dup dup currentrgbcolor 77 | 4 -2 roll dup 1 exch sub 3 -1 roll mul add 78 | 4 -2 roll dup 1 exch sub 3 -1 roll mul add 79 | 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} 80 | bind def 81 | /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 82 | 4 -2 roll mul srgb} bind def 83 | /DrawEllipse { 84 | /endangle exch def 85 | /startangle exch def 86 | /yrad exch def 87 | /xrad exch def 88 | /y exch def 89 | /x exch def 90 | /savematrix mtrx currentmatrix def 91 | x y tr xrad yrad sc 0 0 1 startangle endangle arc 92 | closepath 93 | savematrix setmatrix 94 | } def 95 | 96 | /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def 97 | /$F2psEnd {$F2psEnteredState restore end} def 98 | 99 | $F2psBegin 100 | 10 setmiterlimit 101 | 0 slj 0 slc 102 | 0.06299 0.06299 sc 103 | % 104 | % Fig objects follow 105 | % 106 | % 107 | % here starts figure with depth 50 108 | % Ellipse 109 | 7.500 slw 110 | n 3150 450 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr 111 | 112 | % Ellipse 113 | n 2475 900 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr 114 | 115 | % Ellipse 116 | n 3825 900 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr 117 | 118 | % Ellipse 119 | n 3375 1800 90 90 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr 120 | 121 | % Polyline 122 | 0 slj 123 | 0 slc 124 | 15.000 slw 125 | n 3375 1800 m 126 | 3600 2700 l gs col0 s gr 127 | % Polyline 128 | n 3375 1800 m 129 | 3150 2700 l gs col0 s gr 130 | % Polyline 131 | n 3825 900 m 132 | 3375 1800 l gs col0 s gr 133 | % Polyline 134 | n 3825 900 m 135 | 4275 1800 l gs col0 s gr 136 | % Polyline 137 | n 3150 450 m 138 | 3825 900 l gs col0 s gr 139 | % Polyline 140 | n 3150 450 m 141 | 2475 900 l gs col0 s gr 142 | % Polyline 143 | n 2475 900 m 144 | 2925 1800 l gs col0 s gr 145 | % Polyline 146 | n 2475 900 m 147 | 2025 1800 l gs col0 s gr 148 | % here ends figure; 149 | $F2psEnd 150 | rs 151 | showpage 152 | %%Trailer 153 | %EOF 154 | -------------------------------------------------------------------------------- /images/baum_pspdftex.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/baum_pspdftex.pdf -------------------------------------------------------------------------------- /images/bird.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/bird.png -------------------------------------------------------------------------------- /images/book-knuth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/book-knuth.png -------------------------------------------------------------------------------- /images/book-onag.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/book-onag.jpeg -------------------------------------------------------------------------------- /images/book-onag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/book-onag.png -------------------------------------------------------------------------------- /images/book-winning-ways.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/book-winning-ways.jpeg -------------------------------------------------------------------------------- /images/bridge.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/bridge.jpeg -------------------------------------------------------------------------------- /images/bug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/bug.png -------------------------------------------------------------------------------- /images/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/cloud.png -------------------------------------------------------------------------------- /images/committee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/committee.png -------------------------------------------------------------------------------- /images/comonads-cofun.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/comonads-cofun.jpeg -------------------------------------------------------------------------------- /images/cryptol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/cryptol.png -------------------------------------------------------------------------------- /images/darcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/darcs.png -------------------------------------------------------------------------------- /images/dedekind-titleslide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/dedekind-titleslide.png -------------------------------------------------------------------------------- /images/dedekind-toc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/dedekind-toc.png -------------------------------------------------------------------------------- /images/definition-free-monad.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad (join) 2 | 3 | data Free f a 4 | = Pure a 5 | | Roll (f (Free f a)) 6 | 7 | liftF :: (Functor f) => f a -> Free f a 8 | liftF = Roll . fmap Pure 9 | 10 | instance (Functor f) => Functor (Free f) where 11 | fmap h (Pure x) = Pure (h x) 12 | fmap h (Roll u) = Roll (fmap (fmap h) u) 13 | 14 | instance (Functor f) => Monad (Free f) where 15 | return x = Pure x 16 | m >>= k = join_ $ fmap k m 17 | where 18 | join_ (Pure u) = u 19 | join_ (Roll v) = Roll (fmap join_ v) 20 | 21 | can :: (Functor f, Monad m) 22 | => (forall a. f a -> m a) 23 | -> (forall a. Free f a -> m a) 24 | can phi (Pure x) = return x 25 | can phi (Roll u) = join $ phi . fmap (can phi) $ u 26 | -- oder: join $ fmap (can phi) . phi $ u 27 | -------------------------------------------------------------------------------- /images/do-stuff.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/do-stuff.jpeg -------------------------------------------------------------------------------- /images/effects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/effects.png -------------------------------------------------------------------------------- /images/endo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/endo.png -------------------------------------------------------------------------------- /images/example-free-monad.hs: -------------------------------------------------------------------------------- 1 | data Instr s next = Get (s -> next) | Put s next 2 | deriving (Functor) 3 | 4 | put x = liftF (Put x ()) 5 | 6 | get :: Free (Instr s) s 7 | get = Roll $ Get $ \s -> Pure s 8 | 9 | eval :: Free (Instr s) a -> s -> (a,s) 10 | eval (Pure x) s = (x,s) 11 | eval (Roll u) s 12 | | Put s' v <- u = eval v s' 13 | | Get k <- u = eval (k s) s 14 | 15 | uneval :: (s -> (a,s)) -> Free (Instr s) a 16 | uneval k = do 17 | s <- get 18 | let (x,s) = k s 19 | put s 20 | return x 21 | 22 | -- eval . uneval == id, aber nicht uneval . eval == id. 23 | -------------------------------------------------------------------------------- /images/forest.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/forest.jpeg -------------------------------------------------------------------------------- /images/gargoyle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/gargoyle.png -------------------------------------------------------------------------------- /images/haskell-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/haskell-logo.png -------------------------------------------------------------------------------- /images/haskell-spock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/haskell-spock.png -------------------------------------------------------------------------------- /images/hilbert.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/hilbert.jpeg -------------------------------------------------------------------------------- /images/initial-algebras.hs: -------------------------------------------------------------------------------- 1 | data NatF a = Zero | Succ a 2 | type Nat = Mu NatF 3 | -- Typ der (endlichen) Peano-Zahlen 4 | 5 | data IntListF a = Nil | Cons Int a 6 | type IntList = Mu IntListF 7 | -- Typ der (endlichen) Listen von Ints 8 | 9 | data IntTreeF a = Nil | Fork Int a a 10 | type IntTree = Mu IntTreeF 11 | -- Typ der (endlichen) binären Bäume von Ints 12 | -------------------------------------------------------------------------------- /images/io.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/io.jpg -------------------------------------------------------------------------------- /images/jabberwocky.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/jabberwocky.jpg -------------------------------------------------------------------------------- /images/kan-extension.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/kan-extension.jpeg -------------------------------------------------------------------------------- /images/kasse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/kasse.jpg -------------------------------------------------------------------------------- /images/katze.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/katze.jpg -------------------------------------------------------------------------------- /images/lambdaschnecke.fig: -------------------------------------------------------------------------------- 1 | #FIG 3.2 Produced by xfig version 3.2.5b 2 | Landscape 3 | Center 4 | Metric 5 | A4 6 | 100.00 7 | Single 8 | -2 9 | 1200 2 10 | 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 4725 2160 64 64 4725 2160 4789 2160 11 | 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 5085 2295 64 64 5085 2295 5149 2295 12 | 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 4770 720 64 64 4770 720 4834 720 13 | 1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 5580 900 64 64 5580 900 5644 900 14 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 15 | 2295 2115 3645 2115 16 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 17 | 2655 3195 3375 4635 18 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 19 | 3748 2288 4153 3008 20 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 21 | 3375 4815 2160 7200 22 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 23 | 4500 5985 5175 7200 24 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 25 | 2205 2250 2610 2970 26 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 27 | 4230 3240 5535 5310 28 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 29 | 4815 1890 5310 2025 30 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 31 | 5490 3195 6390 4500 32 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 33 | 6300 2115 7380 2385 34 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 35 | 7560 3825 6525 4410 36 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 37 | 6345 3150 7065 3150 38 | 2 1 0 5 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 39 | 6795 5445 7605 4860 40 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 41 | 4365 3060 4365 2295 42 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 43 | 4365 2115 4680 1845 44 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 45 | 5400 2160 5400 3060 46 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 47 | 5535 3105 6165 2160 48 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 49 | 7470 2520 7605 3735 50 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 51 | 6480 4275 6300 3285 52 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 53 | 3600 7200 4320 5760 54 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 55 | 5636 5500 6716 7210 56 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 57 | 5760 5400 6660 5490 58 | 2 1 0 5 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 59 | 6525 4545 7560 4770 60 | 2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 61 | 900 7200 9000 7200 62 | 3 0 0 3 0 7 50 -1 -1 0.000 0 0 0 3 63 | 4635 2430 4725 2700 5040 2520 64 | 0.000 1.000 0.000 65 | 3 0 0 3 0 7 50 -1 -1 0.000 0 0 0 5 66 | 5445 2070 6075 1575 6120 1080 5805 765 5670 810 67 | 0.000 1.000 1.000 1.000 0.000 68 | 3 0 0 3 0 7 50 -1 -1 0.000 0 0 0 4 69 | 4860 1800 5130 1170 5130 765 4905 675 70 | 0.000 1.000 1.000 0.000 71 | -------------------------------------------------------------------------------- /images/lambdaschnecke.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/lambdaschnecke.pdf -------------------------------------------------------------------------------- /images/lambdaschnecke.pdf_t: -------------------------------------------------------------------------------- 1 | \begin{picture}(0,0)% 2 | \includegraphics{lambdaschnecke.pdf}% 3 | \end{picture}% 4 | \setlength{\unitlength}{4144sp}% 5 | % 6 | \begingroup\makeatletter\ifx\SetFigFont\undefined% 7 | \gdef\SetFigFont#1#2#3#4#5{% 8 | \reset@font\fontsize{#1}{#2pt}% 9 | \fontfamily{#3}\fontseries{#4}\fontshape{#5}% 10 | \selectfont}% 11 | \fi\endgroup% 12 | \begin{picture}(8188,6622)(857,-6425) 13 | \end{picture}% 14 | -------------------------------------------------------------------------------- /images/lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/lazy.jpg -------------------------------------------------------------------------------- /images/learn-you-a-haskell-for-great-good.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/learn-you-a-haskell-for-great-good.png -------------------------------------------------------------------------------- /images/lock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/lock.jpg -------------------------------------------------------------------------------- /images/logicomix-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/logicomix-1.jpeg -------------------------------------------------------------------------------- /images/logicomix-2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/logicomix-2.jpeg -------------------------------------------------------------------------------- /images/luga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/luga.png -------------------------------------------------------------------------------- /images/monadic-parser-combinators.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/monadic-parser-combinators.jpeg -------------------------------------------------------------------------------- /images/natural-transformation-law.hs: -------------------------------------------------------------------------------- 1 | fmap f . eta = eta . fmap f 2 | -------------------------------------------------------------------------------- /images/natural-transformation.hs: -------------------------------------------------------------------------------- 1 | eta :: F a -> G a 2 | -------------------------------------------------------------------------------- /images/ordinal-numbers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/ordinal-numbers.png -------------------------------------------------------------------------------- /images/paradox.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/paradox.jpeg -------------------------------------------------------------------------------- /images/paths.pspdftex: -------------------------------------------------------------------------------- 1 | \begin{picture}(0,0)% 2 | \includegraphics{images/paths_pspdftex}% 3 | \end{picture}% 4 | \setlength{\unitlength}{4144sp}% 5 | % 6 | \begingroup\makeatletter\ifx\SetFigFont\undefined% 7 | \gdef\SetFigFont#1#2#3#4#5{% 8 | \reset@font\fontsize{#1}{#2pt}% 9 | \fontfamily{#3}\fontseries{#4}\fontshape{#5}% 10 | \selectfont}% 11 | \fi\endgroup% 12 | \begin{picture}(4358,2740)(1243,-2687) 13 | \put(5281,-361){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$X$}% 14 | }}}} 15 | \put(4651,-556){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$r$}% 16 | }}}} 17 | \put(3406,-1591){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$H$}% 18 | }}}} 19 | \put(2551,-886){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$x$}% 20 | }}}} 21 | \put(3451,-1126){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$q$}% 22 | }}}} 23 | \put(2731,-1756){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$p$}% 24 | }}}} 25 | \put(4871,-1856){\makebox(0,0)[lb]{\smash{{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}$y$}% 26 | }}}} 27 | \end{picture}% 28 | -------------------------------------------------------------------------------- /images/paths_pspdftex.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/paths_pspdftex.pdf -------------------------------------------------------------------------------- /images/philosophen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/philosophen.png -------------------------------------------------------------------------------- /images/philosophiae-newton.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/philosophiae-newton.jpeg -------------------------------------------------------------------------------- /images/present.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/present.png -------------------------------------------------------------------------------- /images/principia-mathematica-1plus1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/principia-mathematica-1plus1.png -------------------------------------------------------------------------------- /images/principia-mathematica.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/principia-mathematica.jpeg -------------------------------------------------------------------------------- /images/pruefung.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/pruefung.jpg -------------------------------------------------------------------------------- /images/regex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/regex.png -------------------------------------------------------------------------------- /images/run-coproduct.hs: -------------------------------------------------------------------------------- 1 | runM :: (Show e) => s -> Coprod (State s) (Err e) a -> IO a 2 | runM st m = do 3 | ref <- newIORef st 4 | elim (embedState ref) embedErr m 5 | 6 | embedState :: IORef s -> State s a -> IO a 7 | embedState ref m = do 8 | st <- readIORef ref 9 | let (x,st') = runState m st 10 | writeIORef ref st' 11 | return x 12 | 13 | embedErr :: (Show e) => Err e a -> IO a 14 | embedErr (Left e) = putStrLn ("Fehler: " ++ show e) >> exitFailure 15 | embedErr (Right x) = return x 16 | -------------------------------------------------------------------------------- /images/rwh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/rwh.jpg -------------------------------------------------------------------------------- /images/sad-cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/sad-cat.jpg -------------------------------------------------------------------------------- /images/sort.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/sort.jpg -------------------------------------------------------------------------------- /images/space.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/space.jpeg -------------------------------------------------------------------------------- /images/stammbaum-der-surrealen-zahlen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/stammbaum-der-surrealen-zahlen.png -------------------------------------------------------------------------------- /images/standard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/standard.jpg -------------------------------------------------------------------------------- /images/statef-functor.hs: -------------------------------------------------------------------------------- 1 | instance Functor StateF where 2 | fmap phi (Get k) = Get (f . k) 3 | fmap phi (Put st k) = Put st (phi k) 4 | -------------------------------------------------------------------------------- /images/stm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/stm.jpg -------------------------------------------------------------------------------- /images/surreal1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/surreal1.png -------------------------------------------------------------------------------- /images/surreal2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/surreal2.png -------------------------------------------------------------------------------- /images/surreal3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/surreal3.png -------------------------------------------------------------------------------- /images/surreal4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/surreal4.png -------------------------------------------------------------------------------- /images/tablette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/tablette.png -------------------------------------------------------------------------------- /images/terminal-coalgebras.hs: -------------------------------------------------------------------------------- 1 | data NatF a = Zero | Succ a 2 | type Nat = Nu NatF 3 | -- Typ der Peano-Zahlen, mit einem Element für +infty: 4 | -- MkNu (Succ (MkNu (Succ (...)))) 5 | 6 | data IntListF a = Nil | Cons Int a 7 | type IntList = Nu IntListF 8 | -- Typ der (endlichen und unendlichen) Listen von Ints 9 | 10 | data IntTreeF a = Nil | Fork Int a a 11 | type IntTree = Nu IntTreeF 12 | -- Typ der (endlichen und unendlichen) binären Int-Bäume 13 | -------------------------------------------------------------------------------- /images/thankyou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/thankyou.png -------------------------------------------------------------------------------- /images/torus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/torus.png -------------------------------------------------------------------------------- /images/types.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/types.jpg -------------------------------------------------------------------------------- /images/typsystem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/typsystem.png -------------------------------------------------------------------------------- /images/universal-property-free-monoid.hs: -------------------------------------------------------------------------------- 1 | cata :: (Monoid m) => (a -> m) -> ([a] -> m) 2 | cata phi [] = unit 3 | cata phi (x:xs) = phi x <> cata phi xs 4 | -------------------------------------------------------------------------------- /images/variable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/variable.jpg -------------------------------------------------------------------------------- /images/where-no-man-has-gone-before.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/where-no-man-has-gone-before.jpeg -------------------------------------------------------------------------------- /images/wtf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/wtf.jpg -------------------------------------------------------------------------------- /images/xmonad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/images/xmonad.png -------------------------------------------------------------------------------- /impossible-maximum.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | type Nat = Integer 4 | 5 | phi :: ([Bool] -> Nat) -> [Bool] 6 | phi f = if f xs >= f ys then xs else ys 7 | where 8 | xs = False : phi (f . (False:)) 9 | ys = True : phi (f . (True:)) 10 | 11 | maxValue :: ([Bool] -> Nat) -> Nat 12 | maxValue f = f (phi f) 13 | -------------------------------------------------------------------------------- /impossible-programs.lhs: -------------------------------------------------------------------------------- 1 | > {-# LANGUAGE FlexibleInstances #-} 2 | > module Main where 3 | 4 | > import Data.Maybe 5 | 6 | *** Scheinbar unmögliche Programme 7 | 8 | Mit [Bool] meinen wir den Typ der unendlichen 0/1-Folgen. 9 | 10 | > p1, p2, p3 :: [Bool] -> Bool 11 | > p1 xs = xs!!3 12 | > p2 xs = xs!!4 13 | > p3 xs = xs!!(2+1) && (xs!!8 || not (xs!!8)) 14 | 15 | > test1 = p1 == p2 16 | > test2 = p1 == p3 17 | 18 | Das liefert einen Fehler über eine fehlende `Eq`-Instanz, oder? 19 | Weit gefehlt! Beide Programme terminieren. `test1` hat den Wert `False`, 20 | `test2` hat den Wert `True`. 21 | 22 | Das ist umso erstaunlicher, wenn man bedenkt, dass `[Bool]` *überabzahlbar 23 | unendlich groß ist*. 24 | 25 | 26 | *** Hintergrund: Abzählbarkeit und Überabzählbarkeit 27 | 28 | Eine Menge heißt genau dann *abzählbar*, wenn es eine unendliche Liste gibt, in 29 | der alle Elemente der Menge vorkommen. 30 | 31 | Prototypbeispiel: Die Menge N der natürlichen Zahlen ist abzählbar. 32 | 33 | 0, 1, 2, 3, 4, ... 34 | 35 | Die Menge Z der ganzen Zahlen ist ebenfalls abzählbar, insbesondere also genau 36 | so groß wie die Menge der natürlichen Zahlen: 37 | 38 | 0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, ... 39 | 40 | Übungsaufgabe: Zeige, dass auch die Menge Q der rationalen Zahlen abzählbar ist. 41 | 42 | Eine Menge heißt genau dann *überabzählbar*, wenn sie nicht abzählbar ist. 43 | 44 | Beispiel (Cantor): Die Menge R der reellen Zahlen ist überabzählbar. 45 | 46 | Oder: Die Menge [Bool] aller unendlichen 0/1-Folgen ist überabzählbar. 47 | 48 | Beweis durch das Cantorsche Diagonalargument: 49 | 50 | Keine Liste von 0/1-Folgen kann *alle* 0/1-Folgen enthalten. Denn wenn zum 51 | Beispiel folgende Liste gegeben ist: 52 | 53 | 01000101011011011... 54 | 11101011111101111... 55 | 10101010101010101... 56 | 11100011100010010... 57 | 10010101100100000... 58 | 11010101100100000... 59 | . 60 | . 61 | . 62 | 63 | Wenn man nun die Diagonale (von oben links nach unten rechts) durchgeht, 64 | und jeweils die Gegenziffer wählt, erhält man eine 0/1-Folge, die sicher 65 | nicht in der Liste vorkommt. Im Beispiel wäre das 66 | 67 | 100110... 68 | 69 | Diese 0/1-Folge kann nicht das erste Element der Liste sein, denn sie 70 | unterscheidet sich vom ersten Element ja an der vordersten Stelle. Sie kann 71 | auch nicht das zweite Element der Liste sein, denn sie unterscheidet sich 72 | vom zweiten Element ja an der zweitvordersten Stelle. Und so weiter! 73 | 74 | 75 | 76 | *** Epsilon 77 | 78 | Sei `p :: [Bool] -> Bool` ein beliebiges Prädikat. 79 | 80 | Falls `p` erfüllbar ist, d.h. falls es eine 0/1-Folge `xs` gibt, sodass `p xs`, 81 | dann soll `epsilon p` irgendeine 0/1-Folge sein, sodass `p (epsilon p)`. 82 | 83 | Falls `p` nicht erfüllbar ist, dann kann `epsilon p` sein, was es möchte. 84 | 85 | > epsilon :: ([Bool] -> Bool) -> [Bool] 86 | > epsilon p = if p (False : xs) 87 | > then False : xs 88 | > else True : epsilon (p . (True:)) 89 | > where xs = epsilon (p . (False:)) 90 | 91 | Etwas schneller geht es dank Laziness so: 92 | 93 | epsilon :: ([Bool] -> Bool) -> [Bool] 94 | epsilon p = h : epsilon (p . (h:)) 95 | where 96 | h = not $ p (False : epsilon (p . (False:))) 97 | 98 | Wer es noch schneller möchte -- sodass auch Code wie `epsilon $ \xs -> xs !! 99 | (10^10)` funktioniert, kann sich den Code von Martín Escardó ansehen. 100 | 101 | 102 | *** Exists 103 | 104 | Sei `p :: [Bool] -> Bool` ein beliebiges Prädikat. 105 | 106 | Falls `p` erfüllbar ist, dann soll `exists p` ein Zeuge dieser Erfüllbarkeit 107 | sein (in einem Maybe verpackt), also eine 0/1-Folge `xs`, sodass `p xs`. 108 | 109 | Falls `p` nicht erfüllbar ist, soll `exists p` `Nothing` sein. 110 | 111 | > exists :: ([Bool] -> Bool) -> Maybe [Bool] 112 | > exists p = if p xs then Just xs else Nothing 113 | > where xs = epsilon p 114 | 115 | 116 | *** Forall 117 | 118 | Sei `p :: [Bool] -> Bool` ein beliebiges Prädikat. 119 | 120 | `forall p` soll dann und nur dann True sein, falls ``p auf jeder 0/1-Folge 121 | konstant `True` ist. 122 | 123 | > forall :: ([Bool] -> Bool) -> Bool 124 | > forall p = isNothing $ exists (not . p) 125 | 126 | Punktfrei geht es auch: 127 | 128 | forall = not . isJust . exists . (not .) 129 | 130 | 131 | *** Eq-Instanz für Funktionen [Bool] -> Bool 132 | 133 | > instance Eq ([Bool] -> Bool) where 134 | > f == g = forall $ \xs -> f xs == g xs 135 | > -- "zwei Prädikate sind genau dann gleich, wenn sie auf jedem Argument 136 | > -- gleich sind" 137 | 138 | 139 | *** Exkurs: Beispiel für eine unstetige Funktion 140 | 141 | Eine Funktion von R nach R ist genau dann stetig, wenn man ihren Graph zeichnen 142 | kann, ohne den Stift abzusetzen. Eine stetige Funktion darf also keine 143 | Sprungstellen besitzen. 144 | 145 | f : R --> R 146 | 147 | x |-> if x < 0 then -1 else if x == 0 then 0 else 1 148 | 149 | Die Signumfunktion! 150 | 151 | Sie ist aber nur definiert auf der Teilmenge 152 | 153 | { x in R | x < 0 oder x = 0 oder x > 0 }. 154 | 155 | Konstruktiv kann man nicht zeigen, dass diese Teilmenge ganz R ist. 156 | Die Funktion ist also nicht als total nachweisbar. 157 | 158 | 159 | *** Wieso funktionieren die "scheinbar unmöglichen Programme"? 160 | 161 | 1. In Haskell kann man nur stetige Funktionen implementieren. (Wie in manchen 162 | Schulen konstruktiver Mathematik auch.) Jede Funktion vom Typ `[Bool] -> Bool` 163 | ist stetig. 164 | 165 | 2. In der Topologie gibt es folgenden Satz: Jede stetige Funktion, deren 166 | Definitionsmenge kompakt ist, ist schon gleichmäßig stetig. 167 | 168 | Die Menge `[Bool]` ist kompakt. (Eigentlich sollte man "Raum" statt "Menge" 169 | sagen. Für Topologie-Fans: Das folgt sofort aus dem Satz von Tychonoff.) 170 | 171 | 3. Im Spezialfall von Funktionen `[Bool] -> Bool` bedeutet gleichmäßig 172 | stetig: Eine solche Funktion ist genau dann gleichmäßig stetig, wenn es eine 173 | Schranke `m` gibt, sodass die Funktion zur Berechnung ihres Ergebnisses nur 174 | die ersten `m` Bits der Folge benötigt (unabhängig von der speziellen 175 | Eingabefolge). 176 | 177 | 4. `epsilon` ruft sich selbst rekursiv auf. Wenn `p` als Schranke `m` hat, dann 178 | hat das im rekursiven Aufruf verwendete Prädikat `(p . (False:))` als 179 | Schranke `m-1`. Also terminiert nach `m` rekursiven Aufrufen das Verfahren. 180 | 181 | 182 | *** Und die Moral von der Geschicht 183 | 184 | In der Frage, ob Gleichheit von Funktionen vom Typ `A -> Bool` entscheidbar 185 | ist, ist es nicht relevant, ob `A` endlich ist oder nicht. Tatsächlich 186 | entscheidend ist, ob `A` *kompakt* ist oder nicht. 187 | 188 | * Endliche Typen sind kompakt. 189 | * `[Bool]` ist kompakt. 190 | * Sind `A` und `B` kompakt, so auch der Produkttyp `(A,B)`. 191 | * `Nat` und `Integer` sind nicht kompakt. 192 | * Der Datentyp der "lazy naturals", welche auch `+infty` enthalten, ist kompakt. 193 | 194 | Übungsaufgaben: 195 | 196 | 1. Übertrage die Funktion `epsilon` -- und damit auch `exists` und `forall`, 197 | auf den Fall von Funktionen `NAT -> Bool` (statt `[Bool] -> Bool`). Dabei 198 | soll `NAT` der Typ der "lazy naturals" sein, zum Beispiel definiert durch: 199 | 200 | data NAT = Zero | Succ NAT 201 | 202 | infty = Succ infty 203 | 204 | 2. Definiere eine Typklasse `Compact` und implementiere Instanzen für 205 | `[Bool]` und `NAT` sowie eine generische Instanz `(Compact a, Compact b) => 206 | Compact (a,b)`. 207 | 208 | 3. Schreibe eine Funktion, die den größten Funktionswert einer gegebenen 209 | Funktion `[Bool] -> Nat` bestimmt. (Lösung in impossible-maximum.hs.) 210 | -------------------------------------------------------------------------------- /initiale-algebren.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/initiale-algebren.pdf -------------------------------------------------------------------------------- /initiale-algebren.tex: -------------------------------------------------------------------------------- 1 | % Kompilieren mit: TEXINPUTS=minted/source: pdflatex -shell-escape % 2 | \documentclass[12pt,compress,ngerman,utf8,t]{beamer} 3 | \usepackage[ngerman]{babel} 4 | \usepackage{ragged2e} 5 | \usepackage{comment} 6 | \usepackage{minted} 7 | \usepackage{wasysym} 8 | \usepackage{tikz} 9 | \usetikzlibrary{calc} 10 | \usepackage[all]{xy} 11 | \usepackage[protrusion=true,expansion=false]{microtype} 12 | 13 | \hypersetup{colorlinks=true} 14 | 15 | \title[Initiale Algebren]{\smiley{} Initiale Algebren \smiley} 16 | \author[Augsburger Curry Club]{} 17 | \date[2016-06-16]{} 18 | 19 | \usetheme{Warsaw} 20 | 21 | \useinnertheme{rectangles} 22 | 23 | \usecolortheme{seahorse} 24 | \definecolor{mypurple}{RGB}{150,0,255} 25 | \setbeamercolor{structure}{fg=mypurple} 26 | \definecolor{myred}{RGB}{150,0,0} 27 | \setbeamercolor*{title}{bg=myred,fg=white} 28 | \setbeamercolor*{titlelike}{bg=myred,fg=white} 29 | 30 | \usefonttheme{serif} 31 | \usepackage[T1]{fontenc} 32 | \usepackage{libertine} 33 | 34 | \newcommand{\slogan}[1]{% 35 | \begin{center}% 36 | \setlength{\fboxrule}{2pt}% 37 | \setlength{\fboxsep}{8pt}% 38 | {\usebeamercolor[fg]{item}\fbox{\usebeamercolor[fg]{normal text}\parbox{0.91\textwidth}{#1}}}% 39 | \end{center}% 40 | } 41 | 42 | \definecolor{darkred}{RGB}{220,0,0} 43 | \newcommand{\hcancel}[5]{% 44 | \tikz[baseline=(tocancel.base)]{ 45 | \node[inner sep=0pt,outer sep=0pt] (tocancel) {#1}; 46 | \draw[darkred, line width=1mm] ($(tocancel.south west)+(#2,#3)$) -- ($(tocancel.north east)+(#4,#5)$); 47 | }% 48 | }% 49 | 50 | \renewcommand{\C}{\mathcal{C}} 51 | \newcommand{\D}{\mathcal{D}} 52 | \newcommand{\id}{\mathrm{id}} 53 | \newcommand{\Id}{\mathrm{Id}} 54 | \newcommand{\Hask}{\mathrm{Hask}} 55 | 56 | \setbeamertemplate{navigation symbols}{} 57 | \setbeamertemplate{headline}{} 58 | 59 | \setbeamertemplate{title page}[default][colsep=-1bp,rounded=false,shadow=false] 60 | \setbeamertemplate{frametitle}[default][colsep=-2bp,rounded=false,shadow=false,center] 61 | 62 | \newcommand*\oldmacro{}% 63 | \let\oldmacro\insertshorttitle% 64 | \renewcommand*\insertshorttitle{% 65 | \oldmacro\hfill\insertframenumber\,/\,\inserttotalframenumber\hfill} 66 | 67 | \newcommand{\hil}[1]{{\usebeamercolor[fg]{item}{\textbf{#1}}}} 68 | \setbeamertemplate{frametitle}{% 69 | \vskip1em% 70 | \leavevmode% 71 | \begin{beamercolorbox}[dp=1ex,center]{}% 72 | \usebeamercolor[fg]{item}{\textbf{\textsf{\Large \insertframetitle}}} 73 | \end{beamercolorbox}% 74 | } 75 | 76 | \setbeamertemplate{footline}{% 77 | \leavevmode% 78 | \hfill% 79 | \begin{beamercolorbox}[ht=2.25ex,dp=1ex,right]{}% 80 | \usebeamerfont{date in head/foot} 81 | \insertframenumber\,/\,\inserttotalframenumber\hspace*{1ex} 82 | \end{beamercolorbox}% 83 | \vskip0pt% 84 | } 85 | 86 | \newcommand{\backupstart}{ 87 | \newcounter{framenumberpreappendix} 88 | \setcounter{framenumberpreappendix}{\value{framenumber}} 89 | } 90 | \newcommand{\backupend}{ 91 | \addtocounter{framenumberpreappendix}{-\value{framenumber}} 92 | \addtocounter{framenumber}{\value{framenumberpreappendix}} 93 | } 94 | 95 | \setbeameroption{show notes} 96 | \setbeamertemplate{note page}[plain] 97 | 98 | \begin{document} 99 | 100 | % http://www.goodwp.com/images/201311/goodwp.com_30317.jpg 101 | {\usebackgroundtemplate{\includegraphics[height=\paperheight]{images/forest}} 102 | \frame{\titlepage\vspace*{16em}}} 103 | 104 | \frame{\tableofcontents} 105 | 106 | \section{Motivation} 107 | 108 | \begin{frame}\frametitle{Motivation} 109 | In der Mathematik und theoretischen Informatik untersucht man oft 110 | \hil{Fixpunktgleichungen}: 111 | \[ x = f(x) \] 112 | Oft ist man am \hil{kleinsten} oder \hil{größten} Fixpunkt interessiert: 113 | \[ \mu f \qquad\text{oder}\qquad \nu f \] 114 | 115 | \centering 116 | \includegraphics{fixpunkt} 117 | \par 118 | \end{frame} 119 | 120 | \begin{frame}[fragile]\frametitle{Motivation} 121 | In der theoretischen Informatik benötigt man aber auch 122 | eine höhere Art von Fixpunkt"`gleichungen"': 123 | \[ X \cong F(X) \] 124 | 125 | \hil{Initiale Algebren} verallgemeinern kleinste Fixpunkte, 126 | \hil{terminale Koalgebren} verallgemeinern größte Fixpunkte. 127 | \medskip 128 | 129 | Wir klären heute folgende Frage: Was bedeutet 130 | \begin{minted}{haskell} 131 | data Nat = Zero | Succ Nat 132 | \end{minted} 133 | eigentlich wirklich? 134 | \medskip 135 | 136 | Zunächst: 137 | "`keine Bottoms, alles endlich"'. 138 | \end{frame} 139 | 140 | 141 | \section{Algebren} 142 | 143 | \subsection{Definition} 144 | 145 | \begin{frame}[fragile]\frametitle{Algebren} 146 | Eine \hil{Algebra} für einen Funktor $F : \C \to \C$ besteht aus 147 | \begin{itemize} 148 | \item einem Objekt $A \in \C$ und 149 | \item einem Morphismus $\alpha : F(A) \to A$ in~$\C$. 150 | \end{itemize} 151 | 152 | \begin{minted}{haskell} 153 | data F a = Nil | Cons Int a -- Beispielfunktor 154 | 155 | instance Functor F where 156 | fmap f Nil = Nil 157 | fmap f (Cons x r) = Cons x (f r) 158 | 159 | productA :: F Int -> Int -- Beispielalgebra 160 | productA Nil = 1 161 | productA (Cons x r) = x * r 162 | \end{minted} 163 | \end{frame} 164 | 165 | \begin{frame}[fragile]{Algebren sind nicht rar!} 166 | \begin{minted}{haskell} 167 | data F a = Nil | Cons Int a 168 | 169 | productA :: F Int -> Int 170 | productA Nil = 1 171 | productA (Cons x r) = x * r 172 | 173 | lengthA :: F Int -> Int 174 | lengthA Nil = 0 175 | lengthA (Cons _ r) = 1 + r 176 | 177 | allNonzeroA :: F Bool -> Bool 178 | allNonzeroA Nil = True 179 | allNonzeroA (Cons x r) = x /= 0 && r 180 | \end{minted} 181 | \end{frame} 182 | 183 | \note{\justifying 184 | Eine Algebra für einen Funktor~$F$ kann man sich vorstellen wie die Anleitung 185 | für einen~$F$-förmigen Rekursionsschritt. Die Rekursion selbst wird aber 186 | nicht ausgeführt. Algebren machen Ideen, wie eine Rekursion zu führen sei, 187 | zu first-class values. 188 | \medskip 189 | 190 | Eine Algebra muss keinerlei Axiome erfüllen (anders als bei Monoiden, Gruppen 191 | oder Ringen). Das erklärt ihr universelles Vorkommen. 192 | \medskip 193 | 194 | Ist der verwendete Funktor~$F$ der zugrundeliegende Funktor einer Monade, so 195 | kann man Axiome an die Algebra stellen. Dann spricht man von "`Algebren 196 | für Monaden"'. In gewisser Hinsicht sind sie für die Mathematik, Logik und 197 | Informatik noch wichtiger als Algebren für Funktoren. Sie sind aber nicht 198 | Gegenstück dieses Vortrags. 199 | \par 200 | } 201 | 202 | \begin{frame}[fragile]{Ein besonderes Beispiel} 203 | \begin{minted}{haskell} 204 | data F a = Nil | Cons Int a 205 | 206 | productA :: F Int -> Int 207 | productA Nil = 1 208 | productA (Cons x r) = x * r 209 | 210 | allNonzeroA :: F Bool -> Bool 211 | allNonzeroA Nil = True 212 | allNonzeroA (Cons x r) = x /= 0 && r 213 | 214 | initialA :: F [Int] -> [Int] 215 | initialA Nil = [] 216 | initialA (Cons x r) = x : r 217 | \end{minted} 218 | \end{frame} 219 | 220 | 221 | \subsection{Morphismen zwischen Algebren} 222 | 223 | \begin{frame}[fragile]{Morphismen zwischen Algebren} 224 | Ein \hil{Morphismus} zwischen~$F$-Algebren 225 | $\alpha : F(A) \to A$ und $\beta : F(B) \to B$ ist ein Morphismus 226 | $g : A \to B$ 227 | sodass das folgende Diagramm kommutiert. 228 | \[ \xymatrixcolsep{3pc}\xymatrixrowsep{3pc}\xymatrix{ 229 | F(A) \ar[r]^\alpha\ar[d]_{\operatorname{fmap} g} & A \ar[d]^g \\ 230 | F(B) \ar[r]_\beta & B 231 | } \] 232 | 233 | \begin{minted}{haskell} 234 | data F a = Nil | Cons Int a 235 | 236 | g :: Int -> Bool 237 | g x = x /= 0 238 | -- g . productA = allNonzeroA . fmap g 239 | \end{minted} 240 | \end{frame} 241 | 242 | 243 | \subsection{Initiale Algebren} 244 | 245 | \begin{frame}[fragile]{Initiale Algebren} 246 | Die "`besondere Beispielalgebra"' hat eine \hil{universelle Eigenschaft}: 247 | Sie ist die \hil{initiale} $F$-Algebra. 248 | 249 | \begin{minted}{haskell} 250 | data F a = Nil | Cons Int a 251 | 252 | initialA :: F [Int] -> [Int] 253 | initialA Nil = [] 254 | initialA (Cons x r) = x : r 255 | 256 | cata :: (F a -> a) -> ([Int] -> a) 257 | cata beta [] = beta Nil 258 | cata beta (x:xs) = beta (Cons x (cata f xs)) 259 | -- cata beta . initialA = beta . fmap (cata beta) 260 | 261 | product :: [Int] -> Int 262 | product = cata productA 263 | \end{minted} 264 | \end{frame} 265 | 266 | \note{\justifying 267 | Eine~$F$-Algebra~$A$ heißt genau dann \emph{initial}, wenn es genau einen 268 | Algebrenmorphismus~$A \to B$ in jede~$F$-Algebra~$B$ gibt. 269 | \medskip 270 | 271 | Ist~\texttt{beta :: F a -> a} eine solche beliebige~\texttt{F}-Algebra, so 272 | ist~\texttt{cata beta :: [Int] -> a} dieser eindeutige Morphismus. 273 | \par 274 | } 275 | 276 | \note{\justifying 277 | Viele (aber nicht alle) Datentypen "`von endlichen Dingen"' in Haskell 278 | sind Beispiele für initiale Algebren: 279 | 280 | \inputminted{haskell}{images/initial-algebras.hs} 281 | 282 | Entsprechend sind viele (strukturell-)rekursive Funktionen Beispiele für 283 | Katamorphismen -- also Morphismen, die uns die universelle Eigenschaft der 284 | initialen Algebren schenkt. 285 | \par 286 | } 287 | 288 | \begin{frame}[fragile]{Gibt es immer initiale Algebren?} 289 | Sei~$F : \C \to \C$ ein Funktor. Gibt es eine initiale~$F$-Algebra? 290 | \pause 291 | Antwort: \hil{Manchmal} (hängt von~$\C$ und~$F$ ab). Aber in 292 | der Kategorie der Haskell-Typen und Haskell-Funktionen immer (zumindest 293 | moralisch), denn man kann sie explizit konstruieren: 294 | \medskip 295 | 296 | \begin{minted}{haskell} 297 | data Mu f = MkMu { outF :: f (Mu f) } 298 | -- mit sozialer Vereinbarung, nur "endliche" Werte zu 299 | -- betrachten. Der Morphismenanteil der initialen 300 | -- Algebra ist MkMu :: f (Mu f) -> Mu f. 301 | 302 | cata :: (Functor f) => (f a -> a) -> (Mu f -> a) 303 | cata g (MkMu r) = g (fmap (cata g r)) 304 | \end{minted} 305 | \pause 306 | 307 | \slogan{Initiale Algebren modellieren Datentypen, für die man Funktionen 308 | heraus durch Rekursion angeben kann.} 309 | \end{frame} 310 | 311 | \note{\justifying 312 | Kategorielles Fun Fact: Ist eine Kategorie sowohl vollständig (besitzt für 313 | jedes kleine Diagramm eines Limes) als auch "`algebraisch vollständig"' 314 | (besitzt für jeden Endofunktor eine initiale Algebra), so ist sie schon dünn 315 | (je zwei parallele Morphismen sind gleich), kommt also von einer Quasiordnung 316 | her. 317 | \medskip 318 | 319 | Das ist ein 320 | \href{https://cstheory.stackexchange.com/questions/21028/algebraically-compact-categories}{Theorem 321 | von Freyd}. 322 | \par 323 | } 324 | 325 | \begin{frame}{Endlichkeit} 326 | Initiale Algebren modellieren Datentypen, für die jeder Wert "`endlich"' ist. 327 | \medskip 328 | 329 | Tatsächlich kann man in vielen Kategorien die initiale Algebra eines 330 | Funktors~$F$ gewinnen als 331 | \[ \mu F = \operatorname{colim}(\emptyset \to F(\emptyset) \to F(F(\emptyset)) \to \cdots). \] 332 | Dabei ist~$\emptyset$ das initiale Objekt (der leere Datentyp~\texttt{Void}). 333 | \end{frame} 334 | 335 | \note{\justifying 336 | Ist~$F$ der Funktor der vorherigen Folien, so realisiert die gezeigte Formel~$\mu F$ 337 | als (Ko-)Limes der Datentypen der leeren Listen, der höchstens 338 | einelementigen Listen, der höchstens zweielementigen Listen, und so 339 | weiter.\par 340 | } 341 | 342 | 343 | \subsection{Lambeks Lemma} 344 | 345 | \begin{frame}{Lambeks Lemma} 346 | Sei~$\alpha : F(A) \to A$ eine initiale Algebra. 347 | Dann ist~$\alpha$ ein Isomorphismus (besitzt einen Umkehrmorphismus). 348 | \medskip 349 | 350 | In diesem Sinn löst~$A$ die Fixpunkt"`gleichung"' 351 | \[ X \cong F(X). \] 352 | Anschaulich: Mit~$\alpha$ konstruiert man neue Werte aus alten. \\ 353 | Die Isomorphie bedeutet, dass jeder Wert aus anderen Werten konstruierbar ist. 354 | \bigskip 355 | \pause 356 | 357 | \centering 358 | \hil{Übungsaufgabe!} \\ 359 | Wie viele Hilfsmorphismen benötigst du? 360 | \par 361 | \end{frame} 362 | 363 | \note{\justifying 364 | Eine Art Umkehrung von Lambeks Lemma gilt nicht: Ist der 365 | Strukturmorphismus~$F(A) \to A$ einer Algebra zufälligerweise ein 366 | Isomorphismus, so heißt das noch nicht, dass sie eine initiale Algebra ist. 367 | \medskip 368 | 369 | Ist die Basiskategorie~$\C$ nämlich eine Partialordnung, so sind initiale 370 | Algebren dasselbe wie kleinste Fixpunkte und terminale Koalgebren dasselbe 371 | wie größte Fixpunkte. Aber nicht jeder Fixpunkt ist ein kleinster. 372 | \par 373 | } 374 | 375 | 376 | \section{Terminale Koalgebren} 377 | 378 | \begin{frame}[fragile]{Terminale Koalgebren} 379 | Eine \hil{Algebra} für einen Funktor $F : \C \to \C$ besteht aus 380 | \begin{itemize} 381 | \item einem Objekt $A \in \C$ und 382 | \item einem Morphismus $\alpha : F(A) \to A$ in~$\C$. 383 | \end{itemize} 384 | \medskip 385 | 386 | Eine \hil{Koalgebra} für einen Funktor $F : \C \to \C$ besteht aus 387 | \begin{itemize} 388 | \item einem Objekt $A \in \C$ und 389 | \item einem Morphismus $\alpha : A \to F(A)$ in~$\C$. 390 | \end{itemize} 391 | \medskip 392 | 393 | \begin{minted}{haskell} 394 | data Nu f = MkNu { outF :: f (Nu f) } 395 | -- ohne sozialen Vertrag! 396 | 397 | ana :: (Functor f) => (a -> f a) -> (a -> Nu f) 398 | ana alpha x = MkNu (fmap (ana alpha) (alpha x)) 399 | \end{minted} 400 | \end{frame} 401 | 402 | \note{\justifying 403 | Eine Koalgebra für einen Funktor~$F$ kann man sich vorstellen wie die Anleitung 404 | für eine~$F$-förmige Beobachtung. Die Beobachtung wird aber nicht "`bis zum 405 | Ende"', verschachtelt, korekursiv ausgeführt, sondern nur für einen Schritt 406 | lang. Koalgebren machen also Ideen, wie eine Korekursion zu führen sei, zu 407 | first-class values. 408 | \medskip 409 | 410 | Eine \emph{terminale Koalgebra} ist eine Koalgebra~$\beta : A \to F(A)$, 411 | sodass für jede Koalgebra~$\alpha : Z \to F(Z)$ genau ein Morphismus~$g : Z 412 | \to A$ mit $\beta \circ g = \operatorname{fmap} g \circ \alpha$ existiert. 413 | \[ \xymatrixcolsep{3pc}\xymatrixrowsep{3pc}\xymatrix{ 414 | Z \ar[r]^\alpha\ar[d]_{g} & F(Z) \ar[d]^{\operatorname{fmap} g} \\ 415 | A \ar[r]_\beta & F(A) 416 | } \] 417 | } 418 | 419 | \note{\justifying 420 | Wir haben bereits gesehen, dass viele Datentypen "`von endlichen Dingen"' in 421 | Haskell initiale Algebren sind. Viele Datentypen "`von nicht notwendigerweise 422 | endlichen Dingen"' sind terminale Koalgebren: 423 | 424 | \inputminted{haskell}{images/terminal-coalgebras.hs} 425 | 426 | Entsprechend sind viele (strukturell-)korekursive Funktionen Beispiele für 427 | Anamorphismen -- also Morphismen, die uns die universellen Eigenschaften 428 | terminaler Koalgebren schenken. 429 | \par 430 | } 431 | 432 | \note{\justifying 433 | Übungsaufgabe: Wieso spricht niemand über terminale Algebren und initiale 434 | Koalgebren? 435 | \par 436 | } 437 | 438 | 439 | \section{Vergleich} 440 | 441 | \begin{frame}[fragile]{Vergleich} 442 | Initiale Algebren modellieren Datentypen, für die man Funktionen 443 | heraus durch Rekursion angeben kann. 444 | 445 | \begin{itemize} 446 | \item Konstruktion von Werten mittels $F(A) \to A$ 447 | \item \mintinline{haskell}{cata :: (F a -> a) -> (Mu F -> a)} 448 | \item "`endlich"' 449 | \end{itemize} 450 | 451 | \bigskip 452 | 453 | Terminale Koalgebren modellieren Datentypen, für die man Funktionen 454 | hinein durch Korekursion angeben kann. 455 | 456 | \begin{itemize} 457 | \item Beobachtung von Werten mittels $A \to F(A)$ 458 | \item \mintinline{haskell}{ana :: (a -> F a) -> (a -> Nu F)} 459 | \item "`endlich oder unendlich"' 460 | \end{itemize} 461 | \end{frame} 462 | 463 | \note{\justifying 464 | Das Wesentliche an einer initialen Algebra~$A$ ist, dass man vermöge der 465 | mitgegebenen Funktion~$F(A) \to A$ Werte von~$A$ \emph{konstruieren} kann. 466 | Wir stellen uns~$F(A)$ als den Datentyp der Konstruktionsbeschreibungen für 467 | Werte von~$A$ vor; die Funktion~$F(A) \to A$ nimmt eine solche Beschreibung 468 | und führt sie aus. 469 | \medskip 470 | 471 | \emph{Beispiel:} \texttt{initialA (Cons x xs)} konstruiert die verlängerte 472 | Liste \texttt{x:xs}. 473 | \medskip 474 | 475 | Das Wesentliche an einer terminalen Koalgebra~$A$ ist, dass man vermöge der 476 | mitgegebenen Funktion~$A \to F(A)$ Werte von~$A$ \emph{beobachten} kann. 477 | Wir stellen uns~$F(A)$ als den Datentyp der möglichen Beobachtungen über 478 | Werte von~$A$ vor. 479 | \medskip 480 | 481 | \emph{Beispiel:} \texttt{terminalCoA xs} beobachtet, ob die übergebene 482 | Liste~\texttt{xs} leer ist oder eine Cons-Zelle ist (aus einem vorderen 483 | Element~\texttt{x} und einer Restliste~\texttt{xs'} besteht). 484 | \par 485 | } 486 | 487 | \note{\justifying 488 | Lambeks Lemma garantiert, dass die zu einer initialen Algebra gehörige 489 | Funktion~$F(A) \to A$ (bzw. die zu einer terminalen Koalgebra gehörige 490 | Funktion~$A \to F(A)$) umkehrbar ist. Daher kann man aus einer initialen 491 | Algebra eine Koalgebra (welche nur in pathologischen Fällen terminal 492 | sein wird) und dual aus einer terminalen Koalgebra eine Algebra machen. 493 | \medskip 494 | 495 | \emph{Beispiel:} Das Wesentliche vom Datentyp der endlichen Listen ist, dass 496 | man seine Werte aus Grundbestandteilen (\texttt{Nil} und \texttt{Cons x}) 497 | sukzessive \emph{konstruieren} kann. Trotzdem kann man seine Werte auch \emph{beobachten} 498 | (prüfen, ob ein Wert \texttt{Nil} ist oder eine Cons-Zelle ist). 499 | \medskip 500 | 501 | \emph{Beispiel:} Das Wesentliche vom Datentyp der nicht notwendigerweise 502 | endlichen Listen ist, dass man seine Werte \emph{beobachten} kann (ist eine solche 503 | Liste leer oder eine Cons-Zelle?). Trotzdem kann man aber auch seine Werte 504 | \emph{konstruieren} (etwa an eine gegebene beliebig lange Liste vorne ein Element 505 | anfügen). 506 | \par 507 | } 508 | 509 | 510 | \section{Ausblick} 511 | 512 | % http://memory-alpha.wikia.com/wiki/Where_No_Man_Has_Gone_Before_(episode) 513 | \usebackgroundtemplate{\includegraphics[width=\paperwidth]{images/where-no-man-has-gone-before}} 514 | \begin{frame}[fragile]{Ausblick} 515 | \begin{itemize} 516 | \item Behandlung von Bottoms durch Wechsel der Kategorie -- 517 | nicht die Kategorie der Mengen, sondern die Kategorie der \hil{Domänen} 518 | (domains) 519 | \pause 520 | 521 | \item Haskell: boldly going where no functor has gone before. 522 | 523 | \begin{minted}{haskell} 524 | data Seltsam = MkSeltsam (Seltsam -> Bool) 525 | \end{minted} 526 | \end{itemize} 527 | \end{frame} 528 | 529 | \note{\justifying 530 | Die Theorie der initialen Algebren und terminalen Koalgebren ist nur der 531 | Anfang. Für Datentypen, die durch eine kompliziertere Rekursionsgleichung 532 | gegeben sind (etwa, wo der verwendete Funktor kontra- statt kovariant ist; wo 533 | der verwendete Funktor in einem Argument ko- und in einem anderen 534 | kontravariant ist; wo es gar keinen erkennbaren Funktor mehr gibt), benötigt 535 | man eine leistungsfähigere Theorie. 536 | \medskip 537 | 538 | Die Kategorie der Domänen hat sich als sehr leistungsfähig erwiesen. In ihr 539 | gibt es viel mehr als nur initiale Algebren und terminale Koalgebren. 540 | \par 541 | } 542 | 543 | \note{\justifying 544 | Mehr zum seltsamen Typ hat 545 | \href{http://blog.sigfpe.com/2008/01/type-that-should-not-be.html}{Dan Piponi 546 | zu berichten}. Der Typ ist durchaus beachtenswert, liefert er doch ein 547 | Gegenbeispiel zu einer (internen Variante von) Cantors Theorem: 548 | \medskip 549 | 550 | In früheren Curry-Club-Vorträgen haben wir gesehen, dass keine Menge~$X$ 551 | isomorph zu ihrer Potenzmenge~$\mathcal{P}(X)$ sein kann. ("`Isomorph"' heißt 552 | hier "`gleich mächtig"' und die Potenzmenge ist die Menge aller Teilmengen 553 | von~$X$, verallgemeinerbarer formuliert als Menge aller Abbildungen von~$X$ 554 | nach~Bool.) 555 | \medskip 556 | 557 | Eine Domäne~$X$ kann aber durchaus isomorph zu ihrer "`Potenzdomäne"'~$(X \to 558 | \mathrm{Bool})$ sein. Das ist etwa bei \texttt{Seltsam} der Fall. 559 | \par 560 | } 561 | 562 | \end{document} 563 | -------------------------------------------------------------------------------- /lightning-talk-tuebix2015.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/lightning-talk-tuebix2015.pdf -------------------------------------------------------------------------------- /lightning-talk-tuebix2015.tex: -------------------------------------------------------------------------------- 1 | % Kompilieren mit: TEXINPUTS=minted/source: xelatex -shell-escape % 2 | \documentclass[12pt,compress,ngerman,utf8,t]{beamer} 3 | \usepackage[ngerman]{babel} 4 | \usepackage{comment} 5 | \usepackage{minted} 6 | \setminted{linenos} 7 | \usepackage[protrusion=true,expansion=false]{microtype} 8 | 9 | \DeclareSymbolFont{extraup}{U}{zavm}{m}{n} 10 | \DeclareMathSymbol{\varheart}{\mathalpha}{extraup}{86} 11 | \DeclareMathSymbol{\vardiamond}{\mathalpha}{extraup}{87} 12 | 13 | \usepackage{etex} 14 | \makeatletter 15 | \globdimenblk\@firsttab{20} 16 | \mathchardef\@maxtab=\numexpr\@firsttab+20-1\relax 17 | \makeatother 18 | 19 | \title{Haskell, eine rein funktionale Programmiersprache} 20 | \author{Ingo Blechschmidt \texttt{}} 21 | \date{T\"ubinger Linuxtag am 13. Juni 2015} 22 | 23 | \usetheme{Warsaw} 24 | 25 | \useinnertheme{rectangles} 26 | 27 | \usecolortheme{seahorse} 28 | \definecolor{mypurple}{RGB}{150,0,255} 29 | \setbeamercolor{structure}{fg=mypurple} 30 | 31 | \usefonttheme{serif} 32 | \usepackage{fontspec} 33 | \defaultfontfeatures{Mapping=tex-text} 34 | \setmainfont{Linux Libertine O} 35 | 36 | \setbeamertemplate{navigation symbols}{} 37 | \setbeamertemplate{headline}{} 38 | 39 | \setbeamertemplate{frametitle}[default][colsep=-2bp,rounded=false,shadow=false,center] 40 | 41 | \renewcommand*\insertshorttitle{% 42 | T\"ubinger Linuxtag} 43 | 44 | \newcommand{\hil}[1]{{\usebeamercolor[fg]{item}{\textbf{#1}}}} 45 | 46 | \begin{document} 47 | 48 | \frame[plain]{\begin{center} 49 | \includegraphics[scale=0.35]{images/learn-you-a-haskell-for-great-good.png} 50 | \end{center}} 51 | 52 | % Was ist schneller als C++, prägnanter als Perl, regelmäßiger als Python, 53 | % flexibler als Ruby, typisierter als C#, robuster als Java und hat 54 | % absolut nichts mit PHP gemeinsam? Es ist Haskell! 55 | 56 | \frame[plain]{\begin{center} 57 | \includegraphics[scale=0.55]{images/haskell-spock} 58 | 59 | \vfill 60 | \begin{itemize} 61 | \item \ \\[-1.1em]\mbox{\hil{Nicht:} Anweisungen, die nacheinander ausgef\"uhrt 62 | werden.} 63 | \pause 64 | \item "`Besteht ein Programm die Typpr\"ufung, so ist es korrekt."' 65 | \end{itemize} 66 | \end{center}} 67 | 68 | \begin{frame}[fragile]\frametitle{Quicksort in C} 69 | \begin{columns} 70 | \begin{column}[b]{0.6\textwidth} 71 | \scriptsize 72 | \begin{minted}{c} 73 | // von rosettacode.org 74 | void quick_sort (int *a, int n) { 75 | int i, j, p, t; 76 | if (n < 2) 77 | return; 78 | p = a[n / 2]; 79 | for (i = 0, j = n - 1;; i++, j--) { 80 | while (a[i] < p) 81 | i++; 82 | while (p < a[j]) 83 | j--; 84 | if (i >= j) 85 | break; 86 | t = a[i]; 87 | a[i] = a[j]; 88 | a[j] = t; 89 | } 90 | quick_sort(a, i); 91 | quick_sort(a + i, n - i); 92 | } 93 | \end{minted} 94 | \end{column} 95 | 96 | \begin{column}{0.2\textwidth} 97 | % http://freephotos.atguru.in/hdphotos/sad-cat/sad-cat-13555.jpg 98 | \includegraphics[scale=0.3,flip]{images/sad-cat.jpg} 99 | \end{column} 100 | \end{columns} 101 | \end{frame} 102 | 103 | \begin{comment} 104 | \begin{frame}[fragile]\frametitle{Quicksort in C\#} 105 | \tiny\vspace{-0.5em} 106 | \begin{minted}{csharp} 107 | // von rosettacode.org 108 | namespace Sort { 109 | using System; 110 | 111 | class QuickSort where T : IComparable { 112 | #region Constants 113 | private const Int32 insertionLimitDefault = 16; 114 | private const Int32 pivotSamples = 5; 115 | #endregion 116 | 117 | #region Properties 118 | public Int32 InsertionLimit { get; set; } 119 | protected Random Random { get; set; } 120 | #endregion 121 | 122 | #region Constructors 123 | public QuickSort() 124 | : this(insertionLimitDefault, new Random()) { 125 | } 126 | 127 | public QuickSort(Int32 insertionLimit, Random random) { 128 | InsertionLimit = insertionLimit; 129 | Random = random; 130 | } 131 | #endregion 132 | 133 | #region Sort Methods 134 | public void Sort(T[] entries) { 135 | Sort(entries, 0, entries.Length - 1); 136 | } 137 | 138 | public void Sort(T[] entries, Int32 first, Int32 last) { 139 | var length = last + 1 - first; 140 | // Elide tail recursion by looping over the longer partition 141 | while (length > 1) { 142 | if (length < InsertionLimit) { 143 | InsertionSort.Sort(entries, first, last); 144 | return; 145 | } 146 | 147 | var median = pivot(entries, first, last); 148 | 149 | var left = first; 150 | var right = last; 151 | partition(entries, median, ref left, ref right); 152 | 153 | var leftLength = right + 1 - first; 154 | var rightLength = last + 1 - left; 155 | 156 | if (leftLength < rightLength) { 157 | Sort(entries, first, right); 158 | first = left; 159 | length = rightLength; 160 | } 161 | else { 162 | Sort(entries, left, last); 163 | last = right; 164 | length = leftLength; 165 | } 166 | } 167 | } 168 | 169 | private T pivot(T[] entries, Int32 first, Int32 last) { 170 | var length = last + 1 - first; 171 | var sampleSize = Math.Min(pivotSamples, length); 172 | var right = first + sampleSize - 1; 173 | for (var left = first; left <= right; left++) { 174 | // Random sampling avoids pathological cases 175 | var random = Random.Next(left, last + 1); 176 | // Sample without replacement 177 | if (left != random) 178 | Swap(entries, left, random); 179 | } 180 | 181 | InsertionSort.Sort(entries, first, right); 182 | return entries[first + sampleSize / 2]; 183 | } 184 | 185 | private static void partition(T[] entries, T pivot, ref Int32 left, ref Int32 right) { 186 | while (left <= right) { 187 | while (pivot.CompareTo(entries[left]) > 0) 188 | left++; // pivot follows entry 189 | while (pivot.CompareTo(entries[right]) < 0) 190 | right--; // pivot precedes entry 191 | 192 | if (left < right) // Move entries to their correct partition 193 | Swap(entries, left++, right--); 194 | else if (left == right) { // No swap needed 195 | left++; 196 | right--; 197 | } 198 | } 199 | } 200 | 201 | public static void Swap(T[] entries, Int32 index1, Int32 index2) { 202 | var entry = entries[index1]; 203 | entries[index1] = entries[index2]; 204 | entries[index2] = entry; 205 | } 206 | #endregion 207 | } 208 | 209 | #region Insertion Sort 210 | static class InsertionSort where T : IComparable { 211 | public static void Sort(T[] entries, Int32 first, Int32 last) { 212 | for (var i = first + 1; i <= last; i++) { 213 | var entry = entries[i]; 214 | var j = i; 215 | while (j > first && entries[j - 1].CompareTo(entry) > 0) 216 | entries[j] = entries[--j]; 217 | entries[j] = entry; 218 | } 219 | } 220 | } 221 | #endregion 222 | } 223 | \end{minted} 224 | \end{frame} 225 | \end{comment} 226 | 227 | \begin{frame}[fragile]\frametitle{Haskell, eine rein funktionale Sprache} 228 | \large\vspace{-0.5em} 229 | \begin{minted}{haskell} 230 | qsort [] = [] 231 | qsort (x:xs) = 232 | qsort kleinere ++ [x] ++ qsort groessere 233 | where 234 | kleinere = [y | y <- xs, y <= x] 235 | groessere = [y | y <- xs, y > x] 236 | \end{minted} 237 | \vfill 238 | 239 | \only<1>{ 240 | \vspace{1em} 241 | \begin{center} 242 | \includegraphics[scale=0.35]{images/katze.jpg} 243 | \end{center} 244 | } 245 | 246 | \pause 247 | Die Fibonaccizahlen: 1, 1, 2, 3, 5, 8, 13, 21, 34, \ldots 248 | \begin{minted}{haskell} 249 | fibs = 1 : 1 : zipWith (+) fibs (tail fibs) 250 | \end{minted} 251 | 252 | \pause 253 | 254 | {\renewcommand{\hil}[1]{{\usebeamercolor[fg]{item}{#1}}} 255 | \newcommand{\lbox}[1]{\framebox{#1}} 256 | \newcommand{\lboxhil}[1]{\hil{\framebox{#1}}} 257 | \only<3>{\begin{tabbing} 258 | \texttt{tail fibs} \= \texttt{=} \= \lbox{1} \= \texttt{:} \= \lbox{1} \= \texttt{:} \= \kill 259 | \> \texttt{fibs} \' \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{1} \> \texttt{:} \> ?? \\ 260 | \texttt{tail fibs} \> \texttt{=} \> \lbox{1} \> \texttt{:} \> ?? \\[-0.5em] 261 | \rule{\linewidth}{\arrayrulewidth} \\ 262 | \> $+$ \' \> \lbox{2} \> \texttt{:} \> ?? 263 | \end{tabbing}} 264 | \only<4>{\begin{tabbing} 265 | \texttt{tail fibs} \= \texttt{=} \= \lbox{1} \= \texttt{:} \= \lbox{1} \= \texttt{:} \= \lbox{2} \= \texttt{:} \= \kill 266 | \> \texttt{fibs} \' \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{1} \> 267 | \texttt{:} \> \lboxhil{2} \> \hil{\texttt{:}} \> \hil{??} \\ 268 | \texttt{tail fibs} \> \texttt{=} \> \lbox{1} \> \texttt{:} \> ?? \\[-0.5em] 269 | \rule{\linewidth}{\arrayrulewidth} \\ 270 | \> $+$ \' \> \lbox{2} \> \texttt{:} \> ?? 271 | \end{tabbing}} 272 | \only<5>{\begin{tabbing} 273 | \texttt{tail fibs} \= \texttt{=} \= \lbox{1} \= \texttt{:} \= \lbox{1} \= \texttt{:} \= \lbox{2} \= \texttt{:} \= \kill 274 | \> \texttt{fibs} \' \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{1} \> 275 | \texttt{:} \> \lboxhil{2} \> \hil{\texttt{:}} \> \hil{??} \\ 276 | \texttt{tail fibs} \> \texttt{=} \> \lbox{1} \> \texttt{:} \> \lboxhil{2} 277 | \> \hil{\texttt{:}} \> \hil{??} \\[-0.5em] 278 | \rule{\linewidth}{\arrayrulewidth} \\ 279 | \> $+$ \' \> \lbox{2} \> \texttt{:} \> ?? 280 | \end{tabbing}} 281 | \only<6>{\begin{tabbing} 282 | \texttt{tail fibs} \= \texttt{=} \= \lbox{1} \= \texttt{:} \= \lbox{1} \= \texttt{:} \= \lbox{2} \= \texttt{:} \= \kill 283 | \> \texttt{fibs} \' \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{1} \> 284 | \texttt{:} \> \lboxhil{2} \> \hil{\texttt{:}} \> \hil{??} \\ 285 | \texttt{tail fibs} \> \texttt{=} \> \lbox{1} \> \texttt{:} \> \lboxhil{2} 286 | \> \hil{\texttt{:}} \> \hil{??} \\[-0.5em] 287 | \rule{\linewidth}{\arrayrulewidth} \\ 288 | \> $+$ \' \> \lbox{2} \> \texttt{:} \> \lboxhil{3} \> \hil{\texttt{:}} \> \hil{??} 289 | \end{tabbing}} 290 | \only<7>{\begin{tabbing} 291 | \texttt{tail fibs} \= \texttt{=} \= \lbox{1} \= \texttt{:} \= \lbox{1} \= \texttt{:} \= \lbox{2} \= \texttt{:} \= \lbox{3} \= \texttt{:} \= \kill 292 | \> \texttt{fibs} \' \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{1} \> \texttt{:} \> \lbox{2} \> \texttt{:} \> \lboxhil{3} \> \hil{\texttt{:}} \> \hil{??} \\ 293 | \texttt{tail fibs} \> \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{2} \> \texttt{:} \> ?? \\[-0.5em] 294 | \rule{\linewidth}{\arrayrulewidth} \\ 295 | \> $+$ \' \> \lbox{2} \> \texttt{:} \> \lbox{3} \> \texttt{:} \> ?? 296 | \end{tabbing}} 297 | \only<8>{\begin{tabbing} 298 | \texttt{tail fibs} \= \texttt{=} \= \lbox{1} \= \texttt{:} \= \lbox{1} \= \texttt{:} \= \lbox{2} \= \texttt{:} \= \lbox{3} \= \texttt{:} \= \kill 299 | \> \texttt{fibs} \' \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{1} \> \texttt{:} \> \lbox{2} \> \texttt{:} \> \lboxhil{3} \> \hil{\texttt{:}} \> \hil{??} \\ 300 | \texttt{tail fibs} \> \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{2} \> \texttt{:} \> \lboxhil{3} \> \hil{\texttt{:}} \> \hil{??} \\[-0.5em] 301 | \rule{\linewidth}{\arrayrulewidth} \\ 302 | \> $+$ \' \> \lbox{2} \> \texttt{:} \> \lbox{3} \> \texttt{:} \> ?? 303 | \end{tabbing}} 304 | \only<9>{\begin{tabbing} 305 | \texttt{tail fibs} \= \texttt{=} \= \lbox{1} \= \texttt{:} \= \lbox{1} \= \texttt{:} \= \lbox{2} \= \texttt{:} \= \lbox{3} \= \texttt{:} \= \kill 306 | \> \texttt{fibs} \' \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{1} \> \texttt{:} \> \lbox{2} \> \texttt{:} \> \lboxhil{3} \> \hil{\texttt{:}} \> \hil{??} \\ 307 | \texttt{tail fibs} \> \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{2} \> \texttt{:} \> \lboxhil{3} \> \hil{\texttt{:}} \> \hil{??} \\[-0.5em] 308 | \rule{\linewidth}{\arrayrulewidth} \\ 309 | \> $+$ \' \> \lbox{2} \> \texttt{:} \> \lbox{3} \> \texttt{:} \> \lboxhil{5} \> \hil{\texttt{:}} \> \hil{??} 310 | \end{tabbing}} 311 | \only<10>{\begin{tabbing} 312 | \texttt{tail fibs} \= \texttt{=} \= \lbox{1} \= \texttt{:} \= \lbox{1} \= \texttt{:} \= \lbox{2} \= \texttt{:} \= \lbox{3} \= \texttt{:} \= \lbox{05} \= \texttt{:} \= \lbox{08} \= \texttt{:} \= \lbox{13} \= \texttt{:} \= \kill 313 | \> \texttt{fibs} \' \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{1} \> \texttt{:} \> \lbox{2} \> \texttt{:} \> \lbox{3} \> \texttt{:} \> \lbox{\phantom{0}5} \> \texttt{:} \> \lbox{\phantom{0}8} \> \texttt{:} \> \lbox{13} \> \texttt{:} \> \ldots \\ 314 | \texttt{tail fibs} \> \texttt{=} \> \lbox{1} \> \texttt{:} \> \lbox{2} \> \texttt{:} \> \lbox{3} \> \texttt{:} \> \lbox{5} \> \texttt{:} \> \lbox{\phantom{0}8} \> \texttt{:} \> \lbox{13} \> \texttt{:} \> \lbox{21} \> \texttt{:} \> \ldots \\[-0.5em] 315 | \rule{\linewidth}{\arrayrulewidth} \\ 316 | \> $+$ \' \> \lbox{2} \> \texttt{:} \> \lbox{3} \> \texttt{:} \> \lbox{5} \> \texttt{:} \> \lbox{8} \> \texttt{:} \> \lbox{13} \> \texttt{:} \> \lbox{21} \> \texttt{:} \> \lbox{34} \> \texttt{:} \> \ldots 317 | \end{tabbing}}} 318 | 319 | \pause 320 | \pause 321 | \pause 322 | \pause 323 | \pause 324 | \pause 325 | \pause 326 | \pause 327 | \begin{center} 328 | \hil{$\varheart$ Statisches Typsystem mit Typerschlie\ss ung $\varheart$} \\ 329 | \hil{rein funktional} \textbullet{} 330 | \hil{nebenl\"aufig} \textbullet{} 331 | \hil{lazy} \textbullet{} 332 | \hil{7000\textsuperscript{+} Pakete} 333 | \end{center} 334 | \end{frame} 335 | 336 | % 337 | % Perl: "Easy things are easy, hard things are possible" 338 | % Haskell: "Hard things are easy, the impossible just happened" 339 | 340 | \end{document} 341 | -------------------------------------------------------------------------------- /lightning-talk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/lightning-talk.pdf -------------------------------------------------------------------------------- /lightning-talk.tex: -------------------------------------------------------------------------------- 1 | % Kompilieren mit: TEXINPUTS=minted/source: xelatex -shell-escape % 2 | \documentclass[12pt,compress,ngerman,utf8,t]{beamer} 3 | \usepackage[ngerman]{babel} 4 | \usepackage{comment} 5 | \usepackage{minted} 6 | \setminted{linenos} 7 | \usepackage[protrusion=true,expansion=false]{microtype} 8 | 9 | \DeclareSymbolFont{extraup}{U}{zavm}{m}{n} 10 | \DeclareMathSymbol{\varheart}{\mathalpha}{extraup}{86} 11 | \DeclareMathSymbol{\vardiamond}{\mathalpha}{extraup}{87} 12 | 13 | \title{Haskell, eine rein funktionale Programmiersprache} 14 | \author{Ingo Blechschmidt \texttt{}} 15 | \date{Augsburger NerdNight am 13. März 2015} 16 | 17 | \usetheme{Warsaw} 18 | 19 | \useinnertheme{rectangles} 20 | 21 | \usecolortheme{seahorse} 22 | \definecolor{mypurple}{RGB}{150,0,255} 23 | \setbeamercolor{structure}{fg=mypurple} 24 | 25 | \usefonttheme{serif} 26 | \usepackage{fontspec} 27 | \defaultfontfeatures{Mapping=tex-text} 28 | \setmainfont{Linux Libertine O} 29 | 30 | \setbeamertemplate{navigation symbols}{} 31 | \setbeamertemplate{headline}{} 32 | 33 | \setbeamertemplate{frametitle}[default][colsep=-2bp,rounded=false,shadow=false,center] 34 | 35 | \renewcommand*\insertshorttitle{% 36 | Erste Augsburger Nerdnight im OpenLab am 13. M\"arz 2015} 37 | 38 | \newcommand{\hil}[1]{{\usebeamercolor[fg]{item}{\textbf{#1}}}} 39 | 40 | \begin{document} 41 | 42 | \frame[plain]{\begin{center} 43 | \includegraphics[scale=0.35]{images/learn-you-a-haskell-for-great-good.png} 44 | \end{center}} 45 | 46 | % Was ist schneller als C++, prägnanter als Perl, regelmäßiger als Python, 47 | % flexibler als Ruby, typisierter als C#, robuster als Java und hat 48 | % absolut nichts mit PHP gemeinsam? Es ist Haskell! 49 | 50 | \begin{frame}[fragile]\frametitle{Quicksort in C} 51 | \begin{columns} 52 | \begin{column}[b]{0.6\textwidth} 53 | \scriptsize 54 | \begin{minted}{c} 55 | // von rosettacode.org 56 | void quick_sort (int *a, int n) { 57 | int i, j, p, t; 58 | if (n < 2) 59 | return; 60 | p = a[n / 2]; 61 | for (i = 0, j = n - 1;; i++, j--) { 62 | while (a[i] < p) 63 | i++; 64 | while (p < a[j]) 65 | j--; 66 | if (i >= j) 67 | break; 68 | t = a[i]; 69 | a[i] = a[j]; 70 | a[j] = t; 71 | } 72 | quick_sort(a, i); 73 | quick_sort(a + i, n - i); 74 | } 75 | \end{minted} 76 | \end{column} 77 | 78 | \begin{column}{0.2\textwidth} 79 | % http://freephotos.atguru.in/hdphotos/sad-cat/sad-cat-13555.jpg 80 | \includegraphics[scale=0.3,flip]{images/sad-cat.jpg} 81 | \end{column} 82 | \end{columns} 83 | \end{frame} 84 | 85 | \begin{comment} 86 | \begin{frame}[fragile]\frametitle{Quicksort in C\#} 87 | \tiny\vspace{-0.5em} 88 | \begin{minted}{csharp} 89 | // von rosettacode.org 90 | namespace Sort { 91 | using System; 92 | 93 | class QuickSort where T : IComparable { 94 | #region Constants 95 | private const Int32 insertionLimitDefault = 16; 96 | private const Int32 pivotSamples = 5; 97 | #endregion 98 | 99 | #region Properties 100 | public Int32 InsertionLimit { get; set; } 101 | protected Random Random { get; set; } 102 | #endregion 103 | 104 | #region Constructors 105 | public QuickSort() 106 | : this(insertionLimitDefault, new Random()) { 107 | } 108 | 109 | public QuickSort(Int32 insertionLimit, Random random) { 110 | InsertionLimit = insertionLimit; 111 | Random = random; 112 | } 113 | #endregion 114 | 115 | #region Sort Methods 116 | public void Sort(T[] entries) { 117 | Sort(entries, 0, entries.Length - 1); 118 | } 119 | 120 | public void Sort(T[] entries, Int32 first, Int32 last) { 121 | var length = last + 1 - first; 122 | // Elide tail recursion by looping over the longer partition 123 | while (length > 1) { 124 | if (length < InsertionLimit) { 125 | InsertionSort.Sort(entries, first, last); 126 | return; 127 | } 128 | 129 | var median = pivot(entries, first, last); 130 | 131 | var left = first; 132 | var right = last; 133 | partition(entries, median, ref left, ref right); 134 | 135 | var leftLength = right + 1 - first; 136 | var rightLength = last + 1 - left; 137 | 138 | if (leftLength < rightLength) { 139 | Sort(entries, first, right); 140 | first = left; 141 | length = rightLength; 142 | } 143 | else { 144 | Sort(entries, left, last); 145 | last = right; 146 | length = leftLength; 147 | } 148 | } 149 | } 150 | 151 | private T pivot(T[] entries, Int32 first, Int32 last) { 152 | var length = last + 1 - first; 153 | var sampleSize = Math.Min(pivotSamples, length); 154 | var right = first + sampleSize - 1; 155 | for (var left = first; left <= right; left++) { 156 | // Random sampling avoids pathological cases 157 | var random = Random.Next(left, last + 1); 158 | // Sample without replacement 159 | if (left != random) 160 | Swap(entries, left, random); 161 | } 162 | 163 | InsertionSort.Sort(entries, first, right); 164 | return entries[first + sampleSize / 2]; 165 | } 166 | 167 | private static void partition(T[] entries, T pivot, ref Int32 left, ref Int32 right) { 168 | while (left <= right) { 169 | while (pivot.CompareTo(entries[left]) > 0) 170 | left++; // pivot follows entry 171 | while (pivot.CompareTo(entries[right]) < 0) 172 | right--; // pivot precedes entry 173 | 174 | if (left < right) // Move entries to their correct partition 175 | Swap(entries, left++, right--); 176 | else if (left == right) { // No swap needed 177 | left++; 178 | right--; 179 | } 180 | } 181 | } 182 | 183 | public static void Swap(T[] entries, Int32 index1, Int32 index2) { 184 | var entry = entries[index1]; 185 | entries[index1] = entries[index2]; 186 | entries[index2] = entry; 187 | } 188 | #endregion 189 | } 190 | 191 | #region Insertion Sort 192 | static class InsertionSort where T : IComparable { 193 | public static void Sort(T[] entries, Int32 first, Int32 last) { 194 | for (var i = first + 1; i <= last; i++) { 195 | var entry = entries[i]; 196 | var j = i; 197 | while (j > first && entries[j - 1].CompareTo(entry) > 0) 198 | entries[j] = entries[--j]; 199 | entries[j] = entry; 200 | } 201 | } 202 | } 203 | #endregion 204 | } 205 | \end{minted} 206 | \end{frame} 207 | \end{comment} 208 | 209 | \begin{frame}[fragile]\frametitle{Haskell, eine rein funktionale Sprache} 210 | \large\vspace{-0.5em} 211 | \begin{minted}{haskell} 212 | qsort [] = [] 213 | qsort (x:xs) = 214 | qsort kleinere ++ [x] ++ qsort groessere 215 | where 216 | kleinere = [y | y <- xs, y <= x] 217 | groessere = [y | y <- xs, y > x] 218 | \end{minted} 219 | \vfill 220 | 221 | \only<1>{ 222 | \vspace{1em} 223 | \begin{center} 224 | \includegraphics[scale=0.35]{images/katze.jpg} 225 | \end{center} 226 | } 227 | 228 | \pause 229 | Die Fibonaccizahlen: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, \ldots 230 | \begin{minted}{haskell} 231 | fibs = 0 : 1 : zipWith (+) fibs (tail fibs) 232 | \end{minted} 233 | 234 | \pause 235 | \begin{center} 236 | \hil{$\varheart$ Statisches Typsystem mit Typerschlie\ss ung $\varheart$} \\ 237 | \hil{rein funktional} \textbullet{} 238 | \hil{nebenl\"aufig} \textbullet{} 239 | \hil{lazy} \textbullet{} 240 | \hil{7000\textsuperscript{+} Pakete} 241 | \end{center} 242 | \end{frame} 243 | 244 | % 245 | % Perl: "Easy things are easy, hard things are possible" 246 | % Haskell: "Hard things are easy, the impossible just happened" 247 | 248 | \end{document} 249 | 250 | Achtung. Bei der Nerdnacht hatte ich vergessen zu erklären, dass das 251 | Quicksort-Beispiel Pattern Matching verwendet. Das hätte nicht passieren 252 | dürfen! Beim Thema Typsystem hätte ich außerdem einen Kommentar der Art 253 | "Tatsächlich ist das Typsystem so stark, dass es folgendes Motto gibt: Code, 254 | der einmal kompiliert, ist bereits korrekt." 255 | 256 | Diese Folien waren für fünf oder sechs Minuten konzipiert. Für einen 257 | 10-minütigen Lightning Talk könnte man das ganze besser machen: 258 | 259 | * Live-Coding statt fertiger Code auf der Folie. 260 | 261 | * Bessere Erklärung des Fibonacci-Beispiels, zum Beispiel so: 262 | 263 | fibs = 0 : 1 : ??? 264 | tail fibs = 1 : ??? 265 | 266 | zipWith (+) fibs (tail fibs) 267 | = 1 : ??? 268 | 269 | Danach aktualisiert man die Folie: 270 | 271 | fibs = 0 : 1 : 1 : ??? 272 | tail fibs = 1 : 1 : ??? 273 | 274 | zipWith (+) fibs (tail fibs) 275 | = 1 : 2 : ??? 276 | 277 | Und so weiter. 278 | 279 | * Stichwörter, wo Haskell eingesetzt wird. 280 | -------------------------------------------------------------------------------- /live-coding-ideen.txt: -------------------------------------------------------------------------------- 1 | * Regexp-Matcher, wie bei 2 | https://github.com/rntz/cps-talk/blob/master/Regexp.hs. 3 | -------------------------------------------------------------------------------- /mandelbrot.b: -------------------------------------------------------------------------------- 1 | A mandelbrot set fractal viewer in brainf*** written by Erik Bosman 2 | +++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[ 3 | >>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+ 4 | <<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>> 5 | >+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+[>>>>>>[>>>>>>>[-]>>]<<<<<<<<<[<<<<<<<<<]>> 6 | >>>>>[-]+<<<<<<++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<+++++++[-[->>> 7 | >>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[[-]>>>>>>[>>>>> 8 | >>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>> 9 | [>>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<< 10 | <<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>+++++++++++++++[[ 11 | >>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[ 12 | >+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[ 13 | -<<+>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<< 14 | <<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<< 15 | [>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>> 16 | >>>>[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+ 17 | <<<<<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>> 18 | >>>>>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<< 19 | +>>>>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<< 20 | <]<+<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>> 21 | >>>>>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>> 22 | >>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<< 23 | <<<]>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<< 24 | <<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[-> 25 | >>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<< 26 | <<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++++++++++++++++ 27 | +++++++>>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>[<<<<<<<+<[-<+>>>>+<<[-]]>[-<<[->+>>>- 28 | <<<<]>>>]>>>>>>>>>>>>>[>>[-]>[-]>[-]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>>>>>>[>>>>> 29 | [-<<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>[-<<<<<<<< 30 | <+>>>>>>>>>]>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>>]+>[- 31 | ]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>>>>>>>]<<< 32 | <<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+>>]< 33 | <[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[->>>> 34 | >>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-]<->>> 35 | [-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-< 36 | <<<<+>>>>>]<<<<<[->>>>>+<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+>>>>>>>> 37 | ]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+ 38 | >>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[> 39 | [->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[- 40 | ]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>> 41 | [>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 42 | ]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+> 43 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++ 44 | +++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-<<<<<<<+ 45 | >>>>>>>]<<<<<<<[->>>>>>>+<<<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[ 46 | -]>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>>]>[-<<<<<<[->>>>>+<++<<<<]>>>>>[-< 47 | <<<<+>>>>>]<->+>]<[->+<]<<<<<[->>>>>+<<<<<]>>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<< 48 | [->>>>->>>>>[>>[-<<->>]+<<[->>->[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-] 49 | +>>>>>>[>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<<<<<<<<<<[<<<<< 50 | <<<<]>>>>[-]+>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<< 51 | [<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<< 52 | <<<+<[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<< 53 | <<<<<+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<< 54 | <<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+<]>>>>>>>>]<<< 55 | <<<<<+<[>[->>>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>[->>>>+<<<<]>]<[->>>>-<<<<<<< 56 | <<<<<<<+>>>>>>>>>>]<]>>[->>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>>+<<<< 57 | ]<<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>>>>>>>>>]<<<<<<<<< 58 | [>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<<<<<< 59 | +>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<<<<<< 60 | <<<<<]]>[-]>>[-]>[-]>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-< 61 | <<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[ 62 | [>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+ 63 | [>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->> 64 | [-<<+>>]<<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<< 65 | <[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[ 66 | >[-]<->>>[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[ 67 | >>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]> 68 | >>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>[-]>>>>+++++++++++++++[[>>>>>>>>>]<<<<<<<<<-<<<<< 69 | <<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<< 70 | <<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[- 71 | <<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>> 72 | >>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>>> 73 | [-<<<->>>]<<<[->>>+<<<]>>>>>>>>]<<<<<<<<+<[>[->+>[-<-<<<<<<<<<<+>>>>>>>>>>>>[-<< 74 | +>>]<]>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<<<]>>[-<+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<]> 75 | [-<<+>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>> 76 | >>>>>>]<<<<<<<<+<[>[->+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>[-<+>]>]<[-<-<<<<<<<<<<+>>>> 77 | >>>>>>>]<<]>>>[-<<+>[-<-<<<<<<<<<<+>>>>>>>>>>>]>]<[-<+>]<<<<<<<<<<<<]>>>>>+<<<<< 78 | ]>>>>>>>>>[>>>[-]>[-]>[-]>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>>>[-<<<<< 79 | <+>>>>>>]<<<<<<[->>>>>>+<<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>> 80 | >]>>[-<<<<<<<[->>>>>+<++<<<<]>>>>>[-<<<<<+>>>>>]<->+>>]<<[->>+<<]<<<<<[->>>>>+<< 81 | <<<]+>>>>[-<<<<->>>>]+<<<<[->>>>->>>>>[>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<< 82 | <<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>[-<<->>]+<<[->>->[-<<<+>>>]< 83 | <<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]< 84 | <<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+ 85 | <]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>[->>>+<<<]>]<[->>>- 86 | <<<<<<<<<<<<<+>>>>>>>>>>]<]>>[->>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>+<<< 87 | ]<<<<<<<<<<<]>>>>>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]]>>>>[-<<<<+> 88 | >>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<<[->>>- 89 | <<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[ 90 | ->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>> 91 | >>]<<<<[->>>>+>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>[>>>>>> 92 | >>>]<<<<<<<<<[>[->>>>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<< 93 | <<<<<+>>>>>>>>>>>]<<]>[->>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<< 94 | <<<<]]>>>>>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>[-<<<<+ 95 | >>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<+>>>>> 96 | ]<<<<<[->>>>>+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>> 97 | >>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>> 98 | >>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[-<<+ 99 | >>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[> 100 | [->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[- 101 | ]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>> 102 | [>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<< 103 | <<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>> 104 | >>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<+>>> 105 | >>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+ 106 | <<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>> 107 | >>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>> 108 | >]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<<<<] 109 | >>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<< 110 | ]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->>>+< 111 | <<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]> 112 | >>>>>>>]<<<<<<<<<[<<<<<<<<<]>>->>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>]<<+>>>>[-<<<< 113 | ->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[-<<<<<<<.>>>>>>>]<<<[-]>[-]>[-]>[-]>[-]>[-]>>>[ 114 | >[-]>[-]>[-]>[-]>[-]>[-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]>>>>]<<<<<<<<< 115 | [<<<<<<<<<]>+++++++++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+>>>>>>>>>+<<<<<<<< 116 | <<<<<<[<<<<<<<<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+[-]>>[>>>>>>>>>]<<<<< 117 | <<<<[>>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<[<<<<<<<<<]>>>>>>>[-]+>>>]<<<< 118 | <<<<<<]]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+>>[>+>>>>[-<<<<->>>>]<<<<[->>> 119 | >+<<<<]>>>>>>>>]<<+<<<<<<<[>>>>>[->>+<<]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<< 120 | <<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<<<<<[->>>>>>+<<<<<<]< 121 | +<<<<<<<<<]>>>>>>>-<<<<[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>->>[>> 122 | >>>[->>+<<]>>>>]<<<<<<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<< 123 | <<<<[->>>>>>+<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+<<< 124 | <<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>->>[-<<<<<<<+>>>>>>>]<<<< 125 | <<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>[-< 126 | <<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<< 127 | <<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<< 128 | <<[<<<<<<<<<]>>>>[-]<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>-<<<<<[<<<<<<< 129 | <<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++[-[->>>>>>>> 130 | >+<<<<<<<<<]>>>>>>>>>]>>>>>+>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<< 131 | <<+>>>>>>>>]<<<<<<<<[->>>>>>>>+[-]>[>>>>>>>>>]<<<<<<<<<[>>>>>>>>[-<<<<<<<+>>>>>> 132 | >]<<<<<<<[->>>>>>>+<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+>>]<<<<<<<<<<]]>>>>>>>>[-<<<<< 133 | <<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+>[>+>>>>>[-<<<<<->>>>>]<<<<<[->>>>>+<<<<<]>>>>>> 134 | >>]<+<<<<<<<<[>>>>>>[->>+<<]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<- 135 | >>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]<+<<<<<< 136 | <<<]>>>>>>>>-<<<<<[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>->[>>> 137 | >>>[->>+<<]>>>]<<<<<<<<<[>[-]<->>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<< 138 | <<<<<[->>>>>>>+<<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>> 139 | +>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<->>>>>>]+< 140 | <<<<<[->>>>>>->>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<< 141 | <<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>> 142 | -<<[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>> 143 | >>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++ 144 | +[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<< 145 | <<<<<]]>>>] 146 | -------------------------------------------------------------------------------- /monadic-parsing-snapshot-der-live-version.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Control.Monad 4 | 5 | -- data Maybe a = Nothing | Just a 6 | 7 | newtype Parser a = MkParser { runParser :: String -> Maybe (String,a) } 8 | 9 | instance Monad Parser where 10 | return = pure 11 | (>>=) = bind 12 | 13 | data Exp = Atom String | List [Exp] 14 | deriving (Show,Eq) 15 | 16 | -- hallo 17 | -- (foo bar baz (...)) 18 | 19 | parseExp :: Parser Exp 20 | parseExp = choice [ parseAtom, parseList ] 21 | 22 | parseAtom :: Parser Exp 23 | parseAtom = do 24 | x <- many1 alphaNum 25 | spaces 26 | return (Atom x) 27 | -- parseAtom = liftM Atom $ many1 alphaNum `andThen` spaces 28 | 29 | parseList :: Parser Exp 30 | parseList = do 31 | token "(" 32 | xs <- many parseExp 33 | token ")" 34 | return $ List xs 35 | 36 | token :: String -> Parser String 37 | token s = string s `andThen` spaces 38 | 39 | string :: String -> Parser String 40 | string s = sequence $ map char s 41 | 42 | makarius :: Parser a -> Parser b -> Parser (a,b) 43 | makarius m n = do 44 | x <- m 45 | y <- n 46 | return (x,y) 47 | -- makarius m n = liftM2 (,) m n 48 | -- makarius = liftM2 (,) 49 | 50 | 51 | alphaNum :: Parser Char 52 | alphaNum = satisfy $ \c -> (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') 53 | 54 | eof :: Parser () 55 | eof = MkParser $ \s -> 56 | case s of 57 | [] -> Just ([], ()) 58 | otherwise -> Nothing 59 | 60 | char :: Char -> Parser Char 61 | char c = MkParser $ \s -> 62 | case s of 63 | (d:cs) | c == d -> Just (cs, c) 64 | otherwise -> Nothing 65 | 66 | bind :: Parser a -> (a -> Parser b) -> Parser b 67 | bind m f = MkParser $ \s -> 68 | case runParser m s of 69 | Just (s', x) -> runParser (f x) s' 70 | Nothing -> Nothing 71 | 72 | choice :: [Parser a] -> Parser a 73 | choice [] = MkParser $ \s -> Nothing 74 | choice (m:ms) = MkParser $ \s -> 75 | case runParser m s of 76 | Just (s', x) -> Just (s', x) 77 | Nothing -> runParser (choice ms) s 78 | 79 | 80 | pure :: a -> Parser a 81 | pure x = MkParser $ \s -> Just (s, x) 82 | 83 | many :: Parser a -> Parser [a] 84 | many m = choice [ bind m (\x -> bind (many m) (\xs -> pure (x:xs))), pure [] ] 85 | 86 | many1 :: Parser a -> Parser [a] 87 | -- many1 m = bind m (\x -> bind (many m) (\xs -> pure (x:xs))) 88 | -- many1 m = m >>= \x -> many m >>= \xs -> return (x:xs) 89 | many1 m = do 90 | x <- m 91 | xs <- many m 92 | return (x:xs) 93 | -- many1 m = liftM2 (:) m (many m) 94 | -- pointless :-) 95 | 96 | {- 97 | irc.freenode.net 98 | /q lambdabot 99 | @pl \x -> x + 3 100 | (+ 3) 101 | -} 102 | 103 | andThen :: Parser a -> Parser b -> Parser a 104 | andThen m n = bind m (\x -> bind n (\y -> pure x)) 105 | 106 | satisfy :: (Char -> Bool) -> Parser Char 107 | satisfy f = MkParser $ \s -> 108 | case s of 109 | (c:cs) | f c -> Just (cs, c) 110 | otherwise -> Nothing 111 | 112 | -- char c = satisfy (== c) 113 | 114 | space :: Parser Char 115 | space = satisfy (== ' ') 116 | 117 | spaces :: Parser [Char] 118 | spaces = many space 119 | 120 | example = bind (char 'a') (\_ -> char 'b') 121 | example' = bind (char 'a') (\c -> char c) 122 | 123 | {- 124 | f $ x = f x 125 | ($) = id 126 | 127 | map ($ x) 128 | -} 129 | -------------------------------------------------------------------------------- /monadic-parsing.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DeriveFunctor #-} 2 | module Main where 3 | 4 | import Data.List 5 | import Control.Monad 6 | import Data.Maybe 7 | 8 | newtype Parser a = MkParser { runParser :: String -> Maybe (String, a) } 9 | deriving (Functor) 10 | -- Also einfach: type Parser = StateT String Maybe 11 | 12 | instance Monad Parser where 13 | return x = MkParser $ \s -> Just (s, x) 14 | m >>= f = MkParser $ \s -> 15 | case runParser m s of 16 | Nothing -> Nothing 17 | Just (s',x) -> runParser (f x) s' 18 | 19 | 20 | 21 | ----------- Beispielanwendung: S-Ausdrücke parsen 22 | 23 | data Exp 24 | = Atom String 25 | | List [Exp] 26 | deriving (Show,Eq) 27 | 28 | parseExp :: Parser Exp 29 | parseExp = choice [ parseSymbol, parseList ] 30 | 31 | parseSymbol :: Parser Exp 32 | parseSymbol = fmap Atom $ many1 alphaNum' `andThen` spaces 33 | where 34 | alphaNum' = choice [ alphaNum, char '+', char '*' ] 35 | 36 | parseList :: Parser Exp 37 | parseList = do 38 | token "(" 39 | elems <- many parseExp 40 | token ")" 41 | return $ List elems 42 | 43 | -- Wenn wir schon dabei sind, können wir Ausdrücke auch noch auswerten. 44 | eval :: Exp -> Integer 45 | eval (Atom x) = read x 46 | eval (List ((Atom "+"):xs)) = sum $ map eval xs 47 | eval (List ((Atom "*"):xs)) = product $ map eval xs 48 | 49 | run :: String -> Integer 50 | run = eval . snd . fromJust . runParser (parseExp `andThen` eof) 51 | 52 | example = run "(+ 1 (* 2 3))" 53 | 54 | 55 | 56 | ----------- Parserkombinatoren 57 | 58 | eof :: Parser () 59 | eof = MkParser $ \s -> if null s then Just (s, ()) else Nothing 60 | 61 | char :: Char -> Parser Char 62 | char x = MkParser $ \s -> 63 | case s of 64 | (x':s') | x == x' -> Just (s', x) 65 | otherwise -> Nothing 66 | 67 | string :: String -> Parser String 68 | string x = MkParser $ \s -> 69 | if x `isPrefixOf` s 70 | then Just (drop (length x) s, x) 71 | else Nothing 72 | 73 | choice :: [Parser a] -> Parser a 74 | choice [] = MkParser $ const Nothing 75 | choice (m:ms) = MkParser $ \s -> 76 | case runParser m s of 77 | Nothing -> runParser (choice ms) s 78 | Just (s',x) -> Just (s',x) 79 | 80 | many :: Parser a -> Parser [a] 81 | many m = choice [ m >>= \x -> liftM (x:) (many m), return [] ] 82 | 83 | many1 :: Parser a -> Parser [a] 84 | many1 m = liftM2 (:) m (many m) 85 | 86 | oneOf :: [Char] -> Parser Char 87 | oneOf = choice . map char 88 | 89 | satisfy :: (Char -> Bool) -> Parser Char 90 | satisfy f = MkParser $ \s -> 91 | case s of 92 | (c:cs) -> if f c then Just (cs,c) else Nothing 93 | otherwise -> Nothing 94 | 95 | digit :: Parser Char 96 | digit = satisfy $ \c -> c >= '0' && c <= '9' 97 | 98 | alphaNum :: Parser Char 99 | alphaNum = satisfy $ \c -> (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') 100 | 101 | skipMany :: Parser a -> Parser () 102 | skipMany m = many m >> return () 103 | 104 | spaces = skipMany $ satisfy (`elem` " \t\n") 105 | 106 | andThen :: Parser a -> Parser b -> Parser a 107 | andThen m n = do 108 | x <- m 109 | n 110 | return x 111 | 112 | token :: String -> Parser String 113 | token x = string x `andThen` spaces 114 | 115 | {- 116 | Probleme an solch naivem Parsing: 117 | 118 | * Da wir vielleicht backtracken müssen, behalten wir in choice 119 | die vollständige Eingabe. Um das zu beheben, sollte man grundsätzlich 120 | zwischen Parses, die schon Zeichen konsumiert haben, und solche, die das 121 | nicht haben, unterscheiden. Das ist die zentrale Idee hinter Parsec. 122 | 123 | * Wir können keine guten Fehlermeldungen ausgeben. 124 | 125 | Zu einer praktikablen Bibliothek fehlen natürlich auch noch Kombinatoren zum 126 | Parsen von Termen mit unterschiedlichen Operatorpräzedenzen. 127 | 128 | Siehe auch: 129 | https://www.cs.nott.ac.uk/~gmh/monparsing.pdf 130 | http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.5200 131 | http://cs.anu.edu.au/people/Clem.Baker-Finch/parsec.pdf 132 | http://www.staff.science.uu.nl/~swier101/Papers/1996/DetErrCorrComPars.pdf 133 | -} 134 | -------------------------------------------------------------------------------- /monadic-parsing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/monadic-parsing.pdf -------------------------------------------------------------------------------- /monadic-parsing.tex: -------------------------------------------------------------------------------- 1 | % Kompilieren mit: TEXINPUTS=minted/source: xelatex -shell-escape % 2 | \documentclass[12pt,compress,ngerman,utf8,t]{beamer} 3 | \usepackage[ngerman]{babel} 4 | \usepackage{comment} 5 | \usepackage{minted} 6 | \setminted{linenos} 7 | \usepackage[protrusion=true,expansion=false]{microtype} 8 | 9 | \DeclareSymbolFont{extraup}{U}{zavm}{m}{n} 10 | \DeclareMathSymbol{\varheart}{\mathalpha}{extraup}{86} 11 | \DeclareMathSymbol{\vardiamond}{\mathalpha}{extraup}{87} 12 | 13 | \title{Monadische Parserkombinatoren} 14 | \author[Curry Club Augsburg]{\texorpdfstring{ 15 | \includegraphics[scale=0.26]{images/regex} \\[0.7em] 16 | \scriptsize Ingo Blechschmidt \\\texttt{} 17 | }{Ingo Blechschmidt}} 18 | \date{23. April 2015} 19 | 20 | \usetheme{Warsaw} 21 | 22 | \useinnertheme{rectangles} 23 | 24 | \usecolortheme{seahorse} 25 | \definecolor{mypurple}{RGB}{150,0,255} 26 | \setbeamercolor{structure}{fg=mypurple} 27 | 28 | \usefonttheme{serif} 29 | \usepackage{fontspec} 30 | \defaultfontfeatures{Mapping=tex-text} 31 | \setmainfont{Linux Libertine O} 32 | 33 | \setbeamertemplate{navigation symbols}{} 34 | \setbeamertemplate{headline}{} 35 | 36 | \setbeamertemplate{title page}[default][colsep=-1bp,rounded=false,shadow=false] 37 | \setbeamertemplate{frametitle}[default][colsep=-2bp,rounded=false,shadow=false,center] 38 | 39 | \newcommand*\oldmacro{}% 40 | \let\oldmacro\insertshorttitle% 41 | \renewcommand*\insertshorttitle{% 42 | \oldmacro\hfill\insertframenumber\,/\,\inserttotalframenumber\hfill} 43 | 44 | \newcommand{\hil}[1]{{\usebeamercolor[fg]{item}{\textbf{#1}}}} 45 | 46 | \begin{document} 47 | 48 | \frame{\titlepage} 49 | 50 | \begin{frame}[fragile]\frametitle{Ziel: S-Ausdr"ucke parsen} 51 | \begin{minted}{haskell} 52 | data Exp = Atom String | List [Exp] 53 | 54 | -- Eingabe: 55 | (+ 1 (* 2 3) (* 4 5)) 56 | 57 | -- Syntaxbaum: 58 | List 59 | [ Atom "+" 60 | , Atom "1" 61 | , List [ Atom "*", Atom "2", Atom "3" ] 62 | , List [ Atom "*", Atom "4", Atom "5" ] 63 | ] 64 | \end{minted} 65 | \end{frame} 66 | 67 | \begin{frame}[fragile]\frametitle{Ziel: S-Ausdr"ucke parsen} 68 | \begin{minted}{haskell} 69 | data Exp = Atom String | List [Exp] 70 | 71 | parseExp :: Parser Exp 72 | parseExp = choice [ parseSymbol, parseList ] 73 | 74 | parseSymbol :: Parser Exp 75 | parseSymbol = 76 | fmap Atom $ many1 alphaNum `andThen` spaces 77 | 78 | parseList :: Parser Exp 79 | parseList = do 80 | token "(" 81 | elems <- many parseExp 82 | token ")" 83 | return $ List elems 84 | \end{minted} 85 | \end{frame} 86 | 87 | \begin{frame} 88 | \begin{center} 89 | % http://learnyouahaskell.com/introduction 90 | \includegraphics[scale=0.5]{images/bird} 91 | 92 | \huge 93 | Live-Coding 94 | \bigskip 95 | 96 | \large 97 | \texttt{\$ vim parsen-macht-spa"s.hs} 98 | \end{center} 99 | \end{frame} 100 | 101 | \begin{frame}\frametitle{Was fehlt noch?} 102 | \begin{itemize} 103 | \item Unsere naive Bibliothek leckt Speicher. 104 | \item Wir geben keine guten Parse-Fehlermeldungen aus. 105 | \item Wir haben keine Kombinatoren zum Parsen von Termen mit Operatoren. 106 | \end{itemize} 107 | \end{frame} 108 | 109 | \begin{frame} 110 | \begin{center} 111 | \includegraphics[scale=0.4]{images/monadic-parser-combinators.jpeg} 112 | \end{center} 113 | \end{frame} 114 | 115 | \end{document} 116 | -------------------------------------------------------------------------------- /surreal.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | type Nat = Int 4 | 5 | 6 | ------------------------------------------------------------------------------- 7 | -- Allgemeines zu Games 8 | ------------------------------------------------------------------------------- 9 | 10 | -- Ein Game besteht aus der Angabe einer Liste von Games, in die der linke 11 | -- Spieler ziehen kann, und einer Liste von Games, in die der rechte Spieler 12 | -- ziehen kann. 13 | data Game = MkGame { left :: [Game], right :: [Game] } 14 | deriving (Show) 15 | 16 | -- Beispiele für Games 17 | zero = MkGame [] [] -- geboren an Tag 0 18 | one = MkGame [zero] [] -- geboren an Tag 1 19 | star = MkGame [zero] [zero] -- geboren an Tag 1 20 | onehalf = MkGame [zero] [one] -- geboren an Tag 2 21 | 22 | -- Das Game `neg x` beschreibt dieselbe Situation wie `x`, nur mit den Rollen 23 | -- des linken und rechten Spielers vertauscht. 24 | neg :: Game -> Game 25 | neg (MkGame xl xr) = MkGame (map neg xr) (map neg xl) 26 | 27 | -- Die folgenden Prädikate bestimmen, ob der linke, rechte, als erstes ziehende 28 | -- oder als zweites ziehende Spieler eine Gewinnstrategie besitzen. 29 | isLeftPlayerWin :: Game -> Bool 30 | isLeftPlayerWin (MkGame xl xr) = any isSecondPlayerWin xl && all isFirstPlayerWin xr 31 | 32 | isRightPlayerWin :: Game -> Bool 33 | isRightPlayerWin g = isLeftPlayerWin (neg g) 34 | 35 | isFirstPlayerWin :: Game -> Bool 36 | isFirstPlayerWin (MkGame xl xr) = any isSecondPlayerWin xl && any isSecondPlayerWin xr 37 | 38 | isSecondPlayerWin :: Game -> Bool 39 | isSecondPlayerWin (MkGame xl xr) = all isFirstPlayerWin xl && all isFirstPlayerWin xr 40 | 41 | -- Seien `x` und `y` Games. Dann beschreibt `x <+> y` die Zusammensetzung 42 | -- aus `x` und `y`. Das kann man sich so vorstellen, dass beide Spiele auf dem 43 | -- Tisch liegen. Ein erlaubter Zug im zusammengesetzten Spiel besteht dann 44 | -- (frei nach Wahl des ziehenden Spielers) entweder aus einem Zug im Spiel `x` 45 | -- oder aus einem Zug im Spiel `y`. 46 | infixl 6 <+> 47 | (<+>) :: Game -> Game -> Game 48 | x@(MkGame xl xr) <+> y@(MkGame yl yr) = 49 | MkGame 50 | ([ x' <+> y | x' <- xl ] ++ [ x <+> y' | y' <- yl ]) 51 | ([ x' <+> y | x' <- xr ] ++ [ x <+> y' | y' <- yr ]) 52 | 53 | -- Praktische Synonyme 54 | isZero = isSecondPlayerWin 55 | isFuzzy = isFirstPlayerWin 56 | isPositive = isLeftPlayerWin 57 | isNegative = isRightPlayerWin 58 | 59 | instance Eq Game where 60 | -- Zwei Games `x` und `y` gelten genau dann als gleich, wenn ihre Differenz 61 | -- Null ist. 62 | x == y = isZero (x <+> neg y) 63 | 64 | 65 | ------------------------------------------------------------------------------- 66 | -- Beispiel: Streichholzspiel 67 | ------------------------------------------------------------------------------- 68 | 69 | -- Beim Streichholzspiel liegen zu Beginn `n` Streichhölzer auf dem Tisch. 70 | -- Abwechselnd müssen der linke und rechte Spieler jeweils zwischen einem und 71 | -- drei Streichhölzer entfernen. Verlierer ist, wer keinen Zug mehr tätigen 72 | -- kann. 73 | -- 74 | -- Das Game `streichholz n` beschreibt die Spielsituation bei `n` Streichhölzern. 75 | streichholz :: Nat -> Game 76 | streichholz n = MkGame gs gs 77 | where gs = map streichholz $ filter (>= 0) [n-3..n-1] 78 | 79 | demo :: [Bool] 80 | demo = map (isFirstPlayerWin . streichholz) [0..20] 81 | 82 | 83 | ------------------------------------------------------------------------------- 84 | -- Nimbers 85 | ------------------------------------------------------------------------------- 86 | 87 | -- Ein Haufen beim Nim-Spiel besteht aus `n` Münzen. Beide Spieler dürfen von 88 | -- einem solchen Haufen eine beliebige Anzahl Münzen wegnehmen (aber mindestens 89 | -- eine). 90 | -- 91 | -- Das Game `nim n` beschreibt einen Nim-Haufen mit `n` Münzen. 92 | nim :: Nat -> Game 93 | nim n 94 | | n == 0 = zero 95 | | otherwise = let gs = map nim [0..n-1] in MkGame gs gs 96 | 97 | -- "Minimum excludant": Bestimmt die kleinste natürliche Zahl, die nicht 98 | -- in der übergebenen Liste enthalten ist. 99 | mex :: [Nat] -> Nat 100 | mex xs = head $ filter (not . (`elem` xs)) [0..] 101 | 102 | -- Die "Nimber-Addition" auf den natürlichen Zahlen 103 | infixl 6 <++> 104 | (<++>) :: Nat -> Nat -> Nat 105 | n <++> m = mex $ [ n' <++> m | n' <- [0..n-1] ] ++ [ n <++> m' | m' <- [0..m-1] ] 106 | 107 | -- Es gilt: nim n <+> nim m = nim (n <++> m) 108 | -------------------------------------------------------------------------------- /surreal.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/surreal.pdf -------------------------------------------------------------------------------- /surreal.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt,compress,ngerman,utf8]{beamer} 2 | \usepackage[ngerman]{babel} 3 | \usepackage{ragged2e} 4 | \usepackage{wasysym} 5 | \usepackage[protrusion=true,expansion=true]{microtype} 6 | 7 | \titlegraphic{\leavevmode\smash{\raisebox{6cm}{\includegraphics[scale=0.25]{images/lambdaschnecke}}}} 8 | \title{\smiley{} Kombinatorische Spieltheorie \smiley{} \\ mit surrealen Zahlen und Haskell} 9 | \author[Augsburger Curry Club]{ 10 | Ingo Blechschmidt \\[0.1em] \scriptsize\texttt{} 11 | } 12 | \date[2016-02-25]{\vspace*{-2.5em}\\\scriptsize Augsburger Curry-Club \\ 25. 13 | Februar 2016} 14 | 15 | \usetheme{Warsaw} 16 | 17 | \useinnertheme{rectangles} 18 | 19 | \usecolortheme{seahorse} 20 | \definecolor{mypurple}{RGB}{150,0,255} 21 | \setbeamercolor{structure}{fg=mypurple} 22 | 23 | \usefonttheme{serif} 24 | \usepackage[T1]{fontenc} 25 | \usepackage{libertine} 26 | 27 | \setbeamertemplate{navigation symbols}{} 28 | \setbeamertemplate{headline}{} 29 | \setbeamertemplate{footline}{} 30 | 31 | \setbeamertemplate{title page}[default][colsep=-1bp,rounded=false,shadow=false] 32 | \setbeamertemplate{frametitle}[default][colsep=-2bp,rounded=false,shadow=false,center] 33 | 34 | \setbeamertemplate{frametitle}{% 35 | \vskip1em% 36 | \leavevmode% 37 | \begin{beamercolorbox}[dp=1ex,center]{}% 38 | \usebeamercolor[fg]{item}{\textbf{\textsf{\Large \insertframetitle}}} 39 | \end{beamercolorbox}% 40 | } 41 | 42 | \begin{document} 43 | 44 | \frame{\vspace*{10em}\titlepage} 45 | 46 | \frame[plain]{\footnotesize\justifying 47 | \begin{itemize}\justifying 48 | \item In der kombinatorischen Spieltheorie untersucht man 49 | Zwei-Personen-Spiele ohne Zufallselemente und ohne verborgene Information. 50 | Verlierer ist, wer keinen Zug mehr tätigen kann. 51 | \item Jeder Spielsituation eines solchen Spiels ordnet man einen Wert zu. 52 | \item Ist dieser positiv, besitzt der linke Spieler eine Gewinnstrategie. 53 | Ist er negativ, besitzt der rechte eine. Ist er Null, so besitzt der als 54 | zweites ziehende Spieler eine Gewinnstrategie. Und ist er "`fuzzy zu 55 | Null"', so besitzt der als erstes ziehende Spieler eine Gewinnstrategie. 56 | \item Die Werte sind nicht gewöhnliche reelle Zahlen, sondern 57 | \emph{surreale Zahlen} oder etwas allgemeiner \emph{Games}. 58 | \item Es gilt ein wichtiges Kompositionalitätsprinzip: Zerfällt eine Spielsituation 59 | in zwei unabhängige Teile, so ist der Gesamtwert die Summe der Einzelwerte. 60 | \item Mögliche Werte sind vertraute Zahlen wie~$0$, $1$, $-1$ 61 | und~$\frac{3}{4}$; aber auch Zahlen wie~$1/\omega$ und~$\omega - 1$. Dabei 62 | ist~$\omega$ eine vornehme Schreibweise für die "`einfachste unendlich große 63 | Zahl"', die es im Bereich der surrealen Zahlen gibt. 64 | \end{itemize} 65 | } 66 | 67 | \frame[plain]{\includegraphics[width=\textwidth]{images/surreal1}} 68 | \frame[plain]{\includegraphics[width=\textwidth]{images/surreal2}} 69 | \frame[plain]{\includegraphics[width=\textwidth]{images/surreal3}} 70 | \frame[plain]{\includegraphics[width=\textwidth]{images/surreal4}} 71 | 72 | \frame[plain]{\includegraphics[width=\textwidth]{images/stammbaum-der-surrealen-zahlen}} 73 | 74 | \frame[plain]{\footnotesize\justifying 75 | Tolle verständliche Quellen für surreale Zahlen und Games sind: 76 | \begin{itemize} 77 | \item \href{https://en.wikipedia.org/wiki/Surreal_number}{Wikipedia. Surreal 78 | numbers.} 79 | \item 80 | \href{https://web.archive.org/web/20151121050005/http://www.tondering.dk/download/sur16.pdf}{Claus 81 | Tøndering. Surreal numbers -- an introduction.} 82 | \item 83 | \href{http://scienceblogs.com/goodmath/2006/08/17/introducing-the-surreal-number/}{Good 84 | Math, Bad Math. Introducing the surreal numbers.} 85 | \item Die drei aufgeführten Bücher. 86 | \end{itemize} 87 | Diese Literatur setzt keine Vorkenntnisse aus einem Mathe-Studium voraus! Sie 88 | ist also auch für euch, liebe Schülerinnen und Schüler, geeignet. Außerdem 89 | gibt es eine Mischung aus Erklärung und Aufgabensammlung: 90 | \begin{itemize} 91 | \item 92 | \href{http://rawgit.com/iblech/mathezirkel-kurs/master/thema02-surreale-zahlen/blatt02.pdf}{Matheschülerzirkel 93 | Augsburg. Surreale Zahlen.} 94 | \end{itemize} 95 | 96 | \hfill 97 | \includegraphics[height=0.4\textheight]{images/book-onag} 98 | \hfill 99 | \includegraphics[height=0.4\textheight]{images/book-winning-ways} 100 | \hfill 101 | \includegraphics[height=0.4\textheight]{images/book-knuth} 102 | \hfill{}{} 103 | } 104 | 105 | \end{document} 106 | -------------------------------------------------------------------------------- /typtheorie.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iblech/vortrag-haskell/8235c5309609c61a37132bb83bccb56e1ed1a6bf/typtheorie.pdf -------------------------------------------------------------------------------- /typtheorie.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt,compress,ngerman,utf8,t]{beamer} 2 | \usepackage{etex} 3 | \usepackage[ngerman]{babel} 4 | \usepackage{ragged2e} 5 | \usepackage{tabto} 6 | \usepackage{wasysym} 7 | \usepackage{booktabs} 8 | \usepackage{mathtools} 9 | \usepackage{tikz} 10 | \usetikzlibrary{calc} 11 | \usepackage[all]{xy} 12 | \usepackage[protrusion=true,expansion=false]{microtype} 13 | 14 | \DeclareSymbolFont{extraup}{U}{zavm}{m}{n} 15 | \DeclareMathSymbol{\varheart}{\mathalpha}{extraup}{86} 16 | \DeclareMathSymbol{\vardiamond}{\mathalpha}{extraup}{87} 17 | 18 | \DeclareUnicodeCharacter{2237}{$\dblcolon$} 19 | \DeclareUnicodeCharacter{21D2}{$\Rightarrow$} 20 | \DeclareUnicodeCharacter{2192}{$\rightarrow$} 21 | 22 | \title[Was sind und was sollen die Typen?]{\smiley{} Was sind und was sollen die Typen? \smiley} 23 | \author[Augsburger Curry Club]{\textcolor{white}{Ingo Blechschmidt \\ Curry Club Augsburg}} 24 | \date[2016-07-14]{\textcolor{white}{14. April 2016}} 25 | 26 | \usetheme{Warsaw} 27 | 28 | \useinnertheme{rectangles} 29 | 30 | \usecolortheme{seahorse} 31 | \definecolor{mypurple}{RGB}{150,0,255} 32 | \setbeamercolor{structure}{fg=mypurple} 33 | \definecolor{myred}{RGB}{150,0,0} 34 | \setbeamercolor*{title}{bg=myred,fg=white} 35 | \setbeamercolor*{titlelike}{bg=myred,fg=white} 36 | 37 | \usefonttheme{serif} 38 | \usepackage[T1]{fontenc} 39 | \usepackage{libertine} 40 | 41 | \newcommand{\slogan}[1]{% 42 | \begin{center}% 43 | \setlength{\fboxrule}{2pt}% 44 | \setlength{\fboxsep}{8pt}% 45 | {\usebeamercolor[fg]{item}\fbox{\usebeamercolor[fg]{normal text}\parbox{0.33\textwidth}{#1}}}% 46 | \end{center}% 47 | } 48 | 49 | \definecolor{darkred}{RGB}{220,0,0} 50 | \newcommand{\hcancel}[5]{% 51 | \tikz[baseline=(tocancel.base)]{ 52 | \node[inner sep=0pt,outer sep=0pt] (tocancel) {#1}; 53 | \draw[darkred, line width=1mm] ($(tocancel.south west)+(#2,#3)$) -- ($(tocancel.north east)+(#4,#5)$); 54 | }% 55 | }% 56 | 57 | \renewcommand{\C}{\mathcal{C}} 58 | \newcommand{\D}{\mathcal{D}} 59 | \newcommand{\id}{\mathrm{id}} 60 | \newcommand{\Id}{\mathrm{Id}} 61 | \newcommand{\Hask}{\mathrm{Hask}} 62 | \newcommand{\defeq}{\vcentcolon=} 63 | \newcommand{\base}{\mathsf{base}} 64 | \newcommand{\lloop}{\mathsf{loop}} 65 | \newcommand{\surf}{\mathsf{surf}} 66 | \newcommand{\merid}{\mathsf{merid}} 67 | \renewcommand{\U}{\mathcal{U}} 68 | \newcommand{\ap}{\mathsf{ap}} 69 | \newcommand{\IsEquiv}{\mathsf{IsEquiv}} 70 | \newcommand{\fib}{\mathsf{fib}} 71 | \newcommand{\UIP}{\mathsf{UIP}} 72 | \newcommand{\ZZ}{\mathbb{Z}} 73 | \newcommand{\inv}{\mathsf{inv}} 74 | \newcommand{\defeqv}{\vcentcolon\equiv} 75 | \newcommand{\IsContr}{\mathsf{IsContr}} 76 | \newcommand{\refl}{\mathsf{refl}} 77 | \newcommand{\IsMereProp}{\mathsf{IsMereProp}} 78 | \newcommand{\NN}{\mathbb{N}} 79 | \newcommand{\ct}{% 80 | \mathchoice{\mathbin{\raisebox{0.5ex}{$\displaystyle\centerdot$}}}% 81 | {\mathbin{\raisebox{0.5ex}{$\centerdot$}}}% 82 | {\mathbin{\raisebox{0.25ex}{$\scriptstyle\,\centerdot\,$}}}% 83 | {\mathbin{\raisebox{0.1ex}{$\scriptscriptstyle\,\centerdot\,$}}} 84 | } 85 | 86 | \setbeamertemplate{navigation symbols}{} 87 | \setbeamertemplate{headline}{} 88 | 89 | \setbeamertemplate{title page}[default][colsep=-1bp,rounded=false,shadow=false] 90 | \setbeamertemplate{frametitle}[default][colsep=-2bp,rounded=false,shadow=false,center] 91 | 92 | \newcommand*\oldmacro{}% 93 | \let\oldmacro\insertshorttitle% 94 | \renewcommand*\insertshorttitle{% 95 | \oldmacro\hfill\insertframenumber\,/\,\inserttotalframenumber\hfill} 96 | 97 | \newcommand{\hil}[1]{{\usebeamercolor[fg]{item}{\textbf{#1}}}} 98 | \setbeamertemplate{frametitle}{% 99 | \vskip1em% 100 | \leavevmode% 101 | \begin{beamercolorbox}[dp=1ex,center]{}% 102 | \usebeamercolor[fg]{item}{\textbf{\textsf{\Large \insertframetitle}}} 103 | \end{beamercolorbox}% 104 | } 105 | 106 | \setbeamertemplate{footline}{% 107 | \leavevmode% 108 | \hfill% 109 | \begin{beamercolorbox}[ht=2.25ex,dp=1ex,right]{}% 110 | \usebeamerfont{date in head/foot} 111 | \insertframenumber\,/\,\inserttotalframenumber\hspace*{1ex} 112 | \end{beamercolorbox}% 113 | \vskip0pt% 114 | } 115 | 116 | \newcommand{\backupstart}{ 117 | \newcounter{framenumberpreappendix} 118 | \setcounter{framenumberpreappendix}{\value{framenumber}} 119 | } 120 | \newcommand{\backupend}{ 121 | \addtocounter{framenumberpreappendix}{-\value{framenumber}} 122 | \addtocounter{framenumber}{\value{framenumberpreappendix}} 123 | } 124 | 125 | \setbeameroption{show notes} 126 | \setbeamertemplate{note page}[plain] 127 | 128 | \newcommand{\imgslide}[1]{{\usebackgroundtemplate{\parbox[c][\paperheight][c]{\paperwidth}{\centering\includegraphics[height=\paperheight]{#1}}}\begin{frame}[plain]\end{frame}}} 129 | \newcommand{\imgslideW}[1]{{\usebackgroundtemplate{\parbox[c][\paperheight][c]{\paperwidth}{\centering\includegraphics[width=\paperwidth]{#1}}}\begin{frame}[plain]\end{frame}}} 130 | 131 | \begin{document} 132 | 133 | % http://www.unoosa.org/res/timeline/index_html/space-2.jpg 134 | {\usebackgroundtemplate{\includegraphics[height=\paperheight]{images/space}} 135 | \frame{\titlepage}} 136 | 137 | {\usebackgroundtemplate{\includegraphics[height=\paperheight]{images/dedekind-titleslide}} 138 | \frame{}} 139 | 140 | \frame{\tableofcontents} 141 | 142 | 143 | \section{Vorgeschichte} 144 | 145 | \begin{frame}{Was sind Grundlagen?} 146 | \begin{itemize} 147 | \item Grundlagen liefern den logischen Rahmen für Mathe. 148 | \item Ihre Details spielen oft keine Rolle. 149 | \item Aber ihre wesentlichen Konzepte schon. 150 | \end{itemize} 151 | 152 | \bigskip 153 | \centering 154 | \includegraphics[scale=0.25]{images/bridge} 155 | \par 156 | \end{frame} 157 | 158 | \imgslideW{images/logicomix-1} 159 | \imgslideW{images/logicomix-2} 160 | 161 | 162 | \note{ 163 | \begin{itemize} 164 | \item\justifying Grundlagen erlauben uns, maximal präzise zu sein. 165 | \item Ein \emph{Beweis} im üblichen mathematischen Sinn ist eine Anleitung, 166 | wie ein (niemals ausbuchstabierter) vollständig formaler Beweis zu 167 | konstruieren wäre. 168 | \item Die Korrektheit von formalen Beweisversuchen kann -- anders als bei 169 | informalen Beweisversuchen -- maschinell geprüft werden. 170 | \end{itemize} 171 | } 172 | 173 | \note{ 174 | \begin{itemize} 175 | \item\justifying Es gibt kein Theorem der Art "`Das Sonnensystem ist genau 176 | dann stabil, wenn das folgende Axiom über große Kardinalzahlen gilt"'. 177 | Resultate in der Mathematik hängen nur sehr selten von speziellen Details 178 | der Fundierung ab. 179 | 180 | \item Brücken werden nicht zusammenbrechen, wenn eine Logikerin eine 181 | Inkonsistenz in Zermelo--Fraenkel-Mengenlehre findet. 182 | \end{itemize} 183 | } 184 | 185 | \begin{frame}[plain,c] 186 | \begin{columns}[c] 187 | \begin{column}{0.6\textwidth} 188 | \includegraphics[scale=0.8]{images/hilbert} 189 | \end{column} 190 | \begin{column}{0.4\textwidth} 191 | Aus dem Paradies, das Cantor uns geschaffen, soll uns niemand vertreiben 192 | können.\medskip 193 | 194 | -- David Hilbert, 1926 195 | 196 | \bigskip 197 | \bigskip 198 | \includegraphics[width=\textwidth]{images/ordinal-numbers} 199 | \end{column} 200 | \end{columns} 201 | \end{frame} 202 | 203 | \imgslide{images/principia-mathematica} 204 | \imgslide{images/principia-mathematica-1plus1} 205 | 206 | {\logo{\includegraphics[scale=0.3]{images/paradox}} 207 | \begin{frame}{Paradoxa} 208 | \begin{itemize} 209 | \item Paradox von Richard 210 | \item Paradox von Curry 211 | \item Die Russellsche Antinomie 212 | \end{itemize} 213 | 214 | Was ist all diesen Paradoxa gemein? 215 | \pause 216 | 217 | \hil{Selbstbezüglichkeit.} 218 | \medskip 219 | 220 | Lösungsvorschläge: \\ 221 | Mengenlehre, Typtheorie. 222 | \end{frame}} 223 | 224 | \note{\justifying 225 | Die Russellsche Antinomie verläuft wie folgt. 226 | \medskip 227 | 228 | Wir definieren die Ansammlung 229 | \[ R \defeq \{ M \,|\, M \not\in M \} \] 230 | derjenigen Mengen, die sich nicht selbst enthalten. (Die meisten Mengen 231 | enthalten sich nicht selbst.) 232 | \par 233 | 234 | Die Aussage~$R \in R$ ist dann, nach Definition, äquivalent zu ihrer 235 | Negation~$R \not\in R$. Das ist ein Widerspruch (wieso genau?). 236 | \par 237 | 238 | Die Russellsche Antinomie hat viele weitere Gesichter: die Barbierin, die 239 | genau diejenigen Leute rasiert, die sich nicht selbst rasieren; der Kreter, 240 | der behauptet, dass alle Kreter lügen; das Adjektiv "`heterolog"'. 241 | \par 242 | } 243 | 244 | 245 | \section{Mengenlehre} 246 | 247 | \begin{frame}{Mengenlehre} 248 | \slogan{Alles ist eine Menge.} 249 | \bigskip 250 | 251 | \begin{itemize} 252 | \item $0 \defeq \emptyset$, \quad 253 | $1 \defeq \{0\}$, \quad 254 | $2 \defeq \{0,1\}$, \quad 255 | $\ldots$ 256 | \item $(x,y) \defeq \{ \{x\}, \{x,y\} \}$ \quad (Kuratowski-Paarung) 257 | \item $(x,y,z) \defeq (x,(y,z))$ 258 | \item Abbildungen sind Tupel $(X,Y,R)$ mit $R \subseteq X \times Y$ und 259 | \ldots 260 | \item \hil{Eingeschränktes Mengenkomprehensionsprinzip.} 261 | \end{itemize} 262 | \end{frame} 263 | 264 | \note{\justifying 265 | Wie wird die Russellsche Antinomie in nicht-naiver Mengenlehre aufgelöst? 266 | \medskip 267 | 268 | Ist~$P(x)$ eine Aussage, die eine freie Variable~$x$ enthält, so kann man 269 | ihre Extension 270 | \[ \{ x \,|\, P(x) \} \] 271 | bilden. Dieser Ausdruck beschreibt zunächst nur eine \emph{Klasse} (oder 272 | \emph{Unmenge} -- vielen Dank an Ludwig Neidhart für diese Sprechweise), 273 | und zwar die Klasse all derjenigen \emph{Mengen}~$x$, für die~$P(x)$ gilt. 274 | Echte Klassen sind nicht eigenständige mathematische Objekte, sondern nur 275 | syntaktischer Zucker. 276 | \medskip 277 | 278 | Die Russellsche Antinomie kann man dann nicht mehr formulieren, weil~"`$R \in 279 | R$"' nicht länger eine wohlgeformte Aussage ist. 280 | \par 281 | } 282 | 283 | \begin{frame}{Mengenlehre?} 284 | Mengentheoretische Grundlagen \ldots 285 | \begin{itemize} 286 | \item spiegeln nicht die typisierte mathematische Praxis wieder, 287 | \item respektieren nicht Äquivalenz von Strukturen und 288 | \item benötigen komplexe Kodierungen von höheren Konzepten -- 289 | zum Nachteil interaktiver Beweisumgebungen. 290 | \end{itemize} 291 | \end{frame} 292 | 293 | \note{ 294 | \begin{itemize} 295 | \item Beispiele für Fragen, die in Mengenlehre formuliert werden können? 296 | \begin{itemize} 297 | \item Ist $2 = (0,0)$? (Nicht bei den von mir angegebenen Definitionen.) 298 | \item Ist $\sin \in \pi$? (Hängt von der nicht angegebenen Definition der 299 | reellen Zahlen ab.) 300 | \end{itemize} 301 | \item\justifying In der mathematischen Praxis befindet man diese Fragen als 302 | unsinnig, denn sie missachten die \emph{Typen} der beteiligten 303 | mathematischen Objekte und sind nicht invariant unter Isomorphie der 304 | beteiligten Strukturen. Man könnte eine konkrete Konstruktion der reellen 305 | Zahlen durch eine andere, gleich gute, ersetzen, und dann andere Antworten 306 | auf diese Fragen erhalten. 307 | \item\justifying Es gibt übrigens auch \emph{strukturelle Ansätze} zu 308 | Mengenlehre ohne ein globales Zugehörigkeitsprädikat (z.\,B. ETCS), die 309 | diesen Mangel beheben. 310 | \end{itemize} 311 | } 312 | 313 | 314 | \section{Extensionale Typtheorie} 315 | 316 | {\logo{\includegraphics[scale=0.3]{images/typsystem}} 317 | \begin{frame}{Extensionale Typtheorie} 318 | \begin{itemize} 319 | \item In Typtheorie gibt es \hil{Werte} und \hil{Typen}. 320 | \item Jeder Wert ist von genau einem Typ. 321 | \item Es gibt kein globales Gleichheitsprädikat. 322 | \end{itemize} 323 | 324 | Aus meiner Sicht beschreibt extensionale Typtheorie genau die Vorstellung von 325 | Mathematikerinnen. 326 | \medskip 327 | 328 | Wie spezifiert man ein Typsystem? 329 | \end{frame}} 330 | 331 | \note{ 332 | \begin{itemize} 333 | \item Wie sehen Regeln für Typen so aus? 334 | \url{https://ncatlab.org/nlab/show/type+theory\#typeforming_rules} 335 | 336 | \item Wie sehen Regeln für die darübergelagerte Logik aus? 337 | siehe Abschnitt~2.3 des Pizzaseminarskripts: 338 | \url{https://pizzaseminar.speicherleck.de/skript2/konstruktive-mathematik.pdf\#page=19} 339 | 340 | \item Geheimtipp von Makarius: 341 | Thompsons \emph{Type Theory and Functional Programming}, 342 | \url{https://www.cs.kent.ac.uk/people/staff/sjt/TTFP/} 343 | \end{itemize} 344 | } 345 | 346 | 347 | \section{Intensionale Typtheorie} 348 | 349 | {\logo{\includegraphics[scale=0.1]{images/torus}} 350 | \begin{frame}{Intensionale Typtheorie} 351 | \begin{itemize} 352 | \item\justifying Intensionale Typtheorie (entwickelt ca. 1960) ist wie 353 | extensionale Typtheorie, nur ohne das Konzept von Aussagen und einer 354 | darübergelagerten Logikschicht. Logik ergibt sich von selbst aus dem 355 | Typsystem! 356 | \item Homotopietyptheorie (vorgestellt 2005 von Voevodsky) ist intensionale 357 | Typtheorie plus das Univalenzaxiom. 358 | \end{itemize} 359 | \end{frame}} 360 | 361 | \note{ 362 | Homotopietyptheorie ist sowohl (Homotopietyp)theorie als auch 363 | Homotopie(typtheorie). 364 | \medskip 365 | 366 | Einige Gründe, wieso manche Mathematikerinnen sich für Homotopietyptheorie 367 | begeistern, sind: Sie ist \ldots 368 | \begin{itemize} 369 | \item elegant, 370 | \item spiegelt die mathematische Praxis wieder, 371 | \item enthält wundersame neue Konzepte (Identitätstypen, Pfadinduktion, Kreisinduktion, 372 | \ldots), 373 | \item stellt sicher, dass alles Äquivalenzen respektiert, 374 | \item vereinfacht die Grundlagen von Homotopietheorie und 375 | \item erlaubt zugängliche Computerformalisierung. 376 | \end{itemize} 377 | } 378 | 379 | \begin{frame}{Gleichheitstypen} 380 | Sei~$X$ eine Menge und seien~$x,y \in X$ Elemente. 381 | \begin{itemize} 382 | \item Dann ist ``$x=y$'' eine \hil{Aussage}. 383 | \end{itemize} 384 | \bigskip 385 | 386 | Sei~$X$ ein Typ in intensionaler Typtheorie und seien~$x,y : X$ Werte. 387 | \begin{itemize} 388 | \item Es gibt einen \hil{Gleichheitstyp} $\Id_X(x,y)$ oder $(x =_X y)$. 389 | \item Um ``$x=y$'' nachzuweisen, 390 | gib einen Wert von~$(x = y)$ an. 391 | \item Wir haben $\refl_x : (x = x)$. 392 | \item Gleichheitstypen können Null oder \hil{viele} Werte enthalten! 393 | \end{itemize} 394 | Intuition: $(x = y)$ ist der Typ der \hil{Beweise} von ``$x=y$''. 395 | 396 | \pause 397 | Intuition: $(x = y)$ ist der Typ der \hil{Pfade} $x \leadsto y$. 398 | \end{frame} 399 | 400 | \note{ 401 | \begin{itemize} 402 | \item In intensionaler Typtheorie sind Aussagen nicht eine zusätzlicher 403 | Bestandteil der Sprache neben Werten und Typen. 404 | \item Stattdessen \emph{sind Aussagen Typen}. 405 | \item Eine Aussage zu beweisen bedeutet, einen Wert von ihr anzugeben. 406 | Ein solcher Wert kann als \emph{Beweis} oder \emph{Zeuge} für die Aussage 407 | angesehen werden. 408 | \item Intensionale Typtheorie ist \emph{beweisrelevant}. 409 | \item Typen, für die je zwei Werte gleich sind, also Typen, für die 410 | lediglich zu wissen, dass sie bewohnt sind, schon alles ist, was man über 411 | sie wissen kann, heißen \emph{mere propositions}. 412 | \end{itemize} 413 | } 414 | 415 | \note{ 416 | \justifying 417 | Beispiele für komplexere Aussagen (Typen): 418 | \begin{itemize} 419 | \item "`$X$ enthält höchstens ein Element"': \tabto{5.45cm} 420 | $\prod_{x:X} \prod_{y:X} (x=y)$ 421 | \item "`Addition ist kommutativ'': \tabto{5.45cm} 422 | $\prod_{n:\NN} \prod_{m:\NN} (n+m = m+n)$ 423 | \item "`Jede natürliche Zahl ist gerade"': \tabto{5.45cm} 424 | $\prod_{n:\NN} \sum_{m:\NN} (n=2m)$ 425 | \end{itemize} 426 | 427 | Indem man "`$\prod_{x:X}$"' als~"`für alle~$x:X$"' und~"`$\sum_{x:X}$"' 428 | als~"`es gibt~$x:X$"' liest, erhalten diese Typen eine logische 429 | Interpretation. Zugleich aber kann man ihnen eine 430 | geometrische/homotopietheoretische Interpretation verleihen. 431 | \par 432 | } 433 | 434 | \note{ 435 | Der Typ der Monoidstrukturen auf einem Typ~$X$ ist 436 | \begin{multline*} 437 | \sum_{\circ:X \times X \to X} 438 | \sum_{e:X} 439 | \Biggl( 440 | \Bigl(\prod_{x:X} (e \circ x = x)\Bigr) \times 441 | \Bigl(\prod_{x:X} (x \circ e = x)\Bigr) \times \\ 442 | \Bigl(\prod_{x,y,z:X} \bigl((x \circ y) \circ z = x \circ (y \circ z)\bigr)\Bigr)\Biggr). 443 | \end{multline*} 444 | } 445 | 446 | \note{ 447 | \begin{itemize} 448 | \item\justifying Identitätszeugen können miteinander komponiert werden: Sei 449 | $p : (x = y)$ und $q : (y = z)$. Dann existiert ein kanonisch definierter 450 | Zeuge~$p \ct q : (x = z)$. 451 | 452 | \item Komposition von Identitätszeugen ist assoziativ. Der Beweis dieser 453 | Tatsache ist ein Wert des Typs 454 | \[ (p \ct (q \ct r) = (p \ct q) \ct r). \] 455 | \end{itemize} 456 | } 457 | 458 | 459 | \begin{frame}{Typen als Räume} 460 | \begin{center}\begin{tabular}{ll} 461 | \toprule 462 | Homotopietheorie & Typtheorie \\\midrule 463 | \hil{Raum} $X$ & Typ $X$ \\ 464 | \hil{Punkt} $x \in X$ & Wert $x:X$ \\ 465 | \hil{Pfad} $x \leadsto y$ & Wert von $(x = y)$ \\ 466 | \hil{(stetige) Abbildung} & Wert von $X \to Y$ \\ 467 | \bottomrule 468 | \end{tabular}\end{center} 469 | 470 | \begin{itemize} 471 | \item Eine \hil{Homotopie} zwischen Abbildungen $f, g : X \to Y$ ist ein 472 | Wert von 473 | \[ (f \simeq g) \defeqv \prod_{x:X} (f(x) = g(x)). \] 474 | \item Ein Raum $X$ ist genau dann \hil{zusammenziehbar}, wenn 475 | \[ \IsContr(X) \defeqv \sum_{x:X} \prod_{y:X} (x=y). \] 476 | \end{itemize} 477 | \end{frame} 478 | 479 | \note{ 480 | \begin{center} 481 | \scalebox{0.6}{\input{images/paths.pspdftex}} 482 | \end{center} 483 | \vspace{-1.3em} 484 | 485 | \begin{itemize} 486 | \item\justifying Dieser Typ~$X$ enthält die Werte~$x, y : X$. 487 | \item Die Pfade~$p$, $q$ und $r$ sind Werte von~$(x = y)$. 488 | \item Da~$p$ und~$q$ "`zueinander homotop sind"', haben wir~$(p = q)$; ein 489 | Zeuge dieses Faktums ist der Wert~$H : (p = q)$. 490 | \item Wegen des Lochs sind $p$ (und~$q$) nicht zu~$r$ homotop. Also $\neg(p 491 | = r)$; genauer gesagt ist der Typ~$\neg(p=r) \defeqv ((p=r) \to 492 | \boldsymbol{0})$ bewohnt, wobei~$\boldsymbol{0}$ der \emph{leere 493 | Typ} ist. 494 | \end{itemize} 495 | } 496 | 497 | \begin{frame}{Induktive Definitionen} 498 | Der \hil{Kreislinie} $S^1$ wird erzeugt von 499 | \begin{itemize} 500 | \item einem Punkt $\base : S^1$ und 501 | \item einem Pfad $\lloop : (\base = \base)$. 502 | \end{itemize} 503 | \bigskip 504 | 505 | Die \hil{Kugeloberfläche} $S^2$ wird erzeugt von 506 | \begin{itemize} 507 | \item einem Punkt $\base : S^2$ und 508 | \item einem 2-Pfad $\surf : (\refl_\base = \refl_\base)$. 509 | \end{itemize} 510 | \bigskip 511 | 512 | Der \hil{Torus} $T^2$ wird erzeugt von 513 | \begin{itemize} 514 | \item einem Punkt $b : T^2$, 515 | \item einem Pfad $p : (b = b)$, 516 | \item einem Pfad $q : (b = b)$ und 517 | \item einem 2-Pfad $t : (p \ct q = q \ct p)$. 518 | \end{itemize} 519 | \end{frame} 520 | 521 | \note{ 522 | \begin{itemize} 523 | \item\justifying Note that a presentation of a type \emph{determines}, but does not 524 | \emph{explicitly describe} its higher identity types. 525 | \item Just like the free vector space spanned by set contains not only the 526 | given elements, but also their linear combinations, the type given by a 527 | higher inductive definition (or its higher identity types) may contain many 528 | more values than explicitly listed. 529 | \item For instance, there is a nontrivial element in $(\refl_{\refl_\base} 530 | = \refl_{\refl_\base})$, where $\base : S^2$, corresponding to the 531 | \emph{Hopf fibration}. 532 | \item More generally, higher-dimensional paths are forced into existence by 533 | \emph{proofs}. For instance, in~$(\base = \base)$ where $\base : S^1$, 534 | there are the values~$\lloop \ct (\lloop \ct \lloop)$ and~$(\lloop \ct 535 | \lloop) \ct \lloop$. They are the same by a witness of type~$(\lloop \ct 536 | (\lloop \ct \lloop) = (\lloop \ct \lloop) \ct \lloop)$. 537 | \item Also, different generators may turn out to give rise to the same 538 | element. 539 | \end{itemize} 540 | } 541 | 542 | \begin{frame}{Pfadinduktion} 543 | \hil{(Based) path induction} sagt aus: Gegeben 544 | \begin{itemize} 545 | \item ein Wert~$a$ eines Typs~$A$, 546 | \item eine Typfamilie~$C : \prod_{x:A} ((a = x) \to \U)$ und 547 | \item einen Wert~$c : C(a,\refl_a)$, 548 | \end{itemize} 549 | dann gibt es eine Funktion 550 | \[ f : \prod_{x:A} \prod_{p:(a=x)} C(x,p) \] 551 | mit~$f(a,\refl_a) \equiv c$. 552 | \end{frame} 553 | 554 | \note{ 555 | \begin{itemize} 556 | \item\justifying In particular, in proving that a proposition depending on a value~$x$ 557 | and an identity witness~$p : (a = x)$ holds for all thoses values and 558 | witnesses, it suffices to prove it for the special value~$a$ and the 559 | canonical identity witness~$\refl_a$. 560 | 561 | \item Note that this does not mean that any value of~$(a = x)$ is equal 562 | to~$\refl_a$! Indeed, this claim is not even well-typed. 563 | 564 | \item The induction principle only makes a statement about the whole \emph{type 565 | family} of the~$(a = x)$'s with~$x$ varying, not about individual types. 566 | 567 | \item Compare with the classical based path space: In it, any element (any 568 | path starting at~$a$) is connected to the trivial path at~$a$. But this 569 | does not mean that any path is homotopic to the trivial path. 570 | \end{itemize} 571 | } 572 | 573 | \note{ 574 | \justifying 575 | As an example, let's define the path reversal function 576 | \[ \inv : \prod_{x:A} ((a = x) \longrightarrow (x = a)), \] 577 | where~$a:A$ is a fixed value, by path induction. For this, we define the type 578 | family 579 | \[ C \defeqv ((x:A, p : (a = x)) \mapsto (x = a)) : \prod_{x:A} ((a = x) \to \U) \] 580 | and note that we have the value 581 | \[ c \defeqv \refl_a : C(a,\refl_a). \] 582 | Therefore, by path induction, we obtain a function 583 | \[ f : \prod_{x:A} \prod_{p:(a=x)} (x=a). \] 584 | This is~$\inv$. 585 | } 586 | 587 | \note{ 588 | \begin{itemize} 589 | \item\justifying 590 | Working informally, we would write the construction more concisely: 591 | 592 | ``Let~$p:(a=x)$ be given, we want to construct~$\inv(p) : (x=a)$. 593 | By path induction, we may assume that~$p \equiv \refl_a$. In this case, we 594 | define~$\inv(p)$ as~$\refl_a$.'' 595 | 596 | \item Here is how we construct the path composition function: 597 | 598 | ``Let~$p:(a=b)$ and~$q:(b=c)$ be given. By path induction, we may assume 599 | that~$p \equiv \refl_a$. Again by path induction, we may assume that~$q 600 | \equiv \refl_a$. In this case, we define~$p \ct q$ as~$\refl_a$.'' 601 | 602 | \item Here is how to construct the function~$\ap_g : (x = y) \to (g(x) = g(y))$, if~$g$ is 603 | some given function: 604 | 605 | ``By path induction, it suffices to define~$\ap_g(p)$ when~$p$ is~$\refl_x$. 606 | In this case, we declare~$\ap_g(p)$ to be~$\refl_{g(x)}$.'' 607 | \end{itemize} 608 | } 609 | 610 | \note{ 611 | \justifying 612 | Path induction does not allow to replace any paths whatsoever by the 613 | canonical reflexivity witnesses. For instance, the following ``proof'' of 614 | \[ p \ct q = q \ct p \] 615 | for all paths~$p$ and~$q$ is bogus: 616 | 617 | ``By path induction, we may assume that~$p$ and~$q$ are~$\refl_a$. In this 618 | case,~$p \ct q$ and~$q \ct p$ both equal~$\refl_a \ct \refl_a = \refl_a$.'' 619 | 620 | Indeed, the claimed statement is not even well-typed: 621 | \[ \prod_{x,y,z:X} \prod_{p:(x=y)} \prod_{q:(y=z)} 622 | (p \ct q = q \ct p). \] 623 | The composition~$q \ct p$ is not defined. Weakening the statement to 624 | \[ \prod_{x:X} \prod_{p:(x=x)} \prod_{q:(x=x)} (p \ct q = q \ct p) \] 625 | does not help either, since in this statement there is no free endpoint, 626 | so path induction does not apply. 627 | } 628 | 629 | 630 | \end{document} 631 | 632 | \subsection{What is the univalence axiom?} 633 | 634 | \frame[t]{\frametitle{What is the univalence axiom?} 635 | An \hil{equivalence} is a function $f : X \to Y$ such that 636 | \[ \IsEquiv(f) \defeqv \prod_{y:Y} \IsContr(\fib_f(y)). \] 637 | 638 | Types $X$ and $Y$ are \hil{equivalent} iff 639 | \[ (X \simeq Y) \defeqv \sum_{f : X \to Y} \IsEquiv(f). \] 640 | 641 | The \hil{univalence axiom} states: The canonical function 642 | \[ (X = Y) \longrightarrow (X \simeq Y) \] 643 | is an equivalence, for all types $X$ and $Y$. 644 | } 645 | 646 | \note{ 647 | \begin{itemize} 648 | \item\justifying Read in logical terms, a function $f : X \to Y$ is an 649 | equivalence if and only if for any~$y:Y$, the fiber~$\fib_f(y)$ is a 650 | singleton, i.\,e.\@ if and only if~$f$ is bijective. 651 | \item One can prove that~$\IsMereProp(\IsEquiv(f))$. 652 | \item A value of~$(X \simeq Y)$ is a pair consisting of a function~$f : X 653 | \to Y$ together with a proof that~$f$ is an equivalence. 654 | \end{itemize} 655 | } 656 | 657 | \note{ 658 | \begin{itemize} 659 | \item\justifying Let~$X$ and~$Y$ be types, i.\,e.\@ values of the 660 | universe~$\U$. Then there is the identity type~$(X = Y)$. What does it 661 | look like? 662 | \item Without the univalence axiom, this question does not have an answer; 663 | the special behaviour of~$(X = Y)$ is left unspecified by the remaining rules 664 | of homotopy type theory. 665 | \item With the univalence axiom, the question has a clear answer: The 666 | type~$(X = Y)$ of identity witnesses is equivalent to the type~$(X \simeq 667 | Y)$ of equivalences. 668 | \end{itemize} 669 | } 670 | 671 | \note{ 672 | \begin{itemize} 673 | \item\justifying The canonical function~$(X = Y) \to (X \simeq Y)$ 674 | appearing in the univalence axiom is constructed by path induction. It maps 675 | the canonical reflexivity witness~$\refl_X$ to the trivial 676 | equivalence~$\id_X : X \to X$ (together with a proof that~$\id_X$ is an 677 | equivalence). 678 | \end{itemize} 679 | } 680 | 681 | \note{ 682 | \begin{itemize} 683 | \item\justifying By the univalence axiom, equivalent types \emph{really are} equal. 684 | \item It implies that isomorphic groups, vector spaces, \ldots\@ are equal. 685 | \item Thus the widespread practice of \emph{pretending} that isomorphic 686 | structures are equal is rigorously formalized. 687 | \item Because any construction has to respect equality, the univalence 688 | axiom guarantees that \emph{any construction respects equivalence}. 689 | \item Most nontrivial mathematical results in homotopy type theory require 690 | the univalence axiom. 691 | \end{itemize} 692 | } 693 | 694 | \note{ 695 | \begin{itemize} 696 | \item\justifying The univalence axiom implies \emph{function 697 | extensionality}: The canonically defined function 698 | \[ (f = g) \longrightarrow \prod_{x:A} (f(x) = g(x)) \] 699 | is an equivalence, for all functions $f,g : A \to B$. 700 | \item So homotopic functions are equal. 701 | \end{itemize} 702 | } 703 | 704 | \note{ 705 | \begin{itemize} 706 | \item\justifying Without the univalence axiom, it is consistent to assume 707 | \emph{uniqueness of identity proofs}, i.\,e.\@ 708 | \[ \UIP \defeqv \prod_{X:\U} \prod_{x,y:X} \prod_{p,q:(x=y)} (p=q), \] 709 | thus collapsing the homotopical universe. 710 | \item Phrased differently, the univalence axiom can not be added to an 711 | \emph{extensional} type theory (one fulfilling $\UIP$). 712 | \end{itemize} 713 | 714 | \begin{itemize} 715 | \item\justifying \emph{No computational interpretation of the univalence axiom is 716 | known yet.} This prevents us from \emph{running} proofs (as computer 717 | programs). If this were possible, we could, for instance, simply run a 718 | proof of the fact that some~$\pi_k(S^n)$ is cyclic (i.\,e.\@ of the 719 | form~$\ZZ/(m)$) to find out the value of~$m$. 720 | \end{itemize} 721 | } 722 | 723 | \end{document} 724 | --------------------------------------------------------------------------------