Haskell.tex 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. \chapter{Haskell}
  2. \index{Haskell|(}
  3. Haskell ist eine funktionale Programmiersprache, die von Haskell
  4. Brooks Curry entwickelt und 1990 in Version~1.0 veröffentlicht
  5. wurde.
  6. Wichtige Konzepte sind:
  7. \begin{enumerate}
  8. \item Funktionen höherer Ordnung
  9. \item anonyme Funktionen (sog. Lambda-Funktionen)
  10. \item Pattern Matching
  11. \item Unterversorgung
  12. \item Typinferenz
  13. \end{enumerate}
  14. Haskell kann mit \enquote{Glasgow Haskell Compiler} mittels
  15. \texttt{ghci} interpretiert und mittels
  16. \section{Erste Schritte}
  17. Haskell kann unter \href{http://www.haskell.org/platform/}{\path{www.haskell.org/platform/}}
  18. für alle Plattformen heruntergeladen werden. Unter Debian-Systemen
  19. ist das Paket \texttt{ghc} bzw. \texttt{haskell-platform} relevant.
  20. \subsection{Hello World}
  21. Speichere folgenden Quelltext als \texttt{hello-world.hs}:
  22. \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=hello-world.hs]{haskell}{scripts/haskell/hello-world.hs}
  23. Kompiliere ihn mit \texttt{ghc -o hello hello-world.hs}. Es wird eine
  24. ausführbare Datei erzeugt.
  25. \section{Syntax}
  26. \subsection{Klammern und Funktionsdeklaration}
  27. Haskell verzichtet an vielen Stellen auf Klammern. So werden im
  28. Folgenden die Funktionen $f(x) := \frac{\sin x}{x}$ und $g(x) := x \cdot f(x^2)$
  29. definiert:
  30. \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/einfaches-beispiel-klammern.hs}
  31. Die Funktionsdeklarationen mit den Typen sind nicht notwendig, da
  32. die Typen aus den benutzten Funktionen abgeleitet werden.
  33. Zu lesen ist die Deklaration wie folgt:
  34. \begin{center}
  35. \texttt{[Funktionsname] :: \texttt{[Typendefinitionen]} => \texttt{Signatur}}
  36. \end{center}
  37. \begin{itemize}
  38. \item[T. Def.] Die Funktion \texttt{f} benutzt als Parameter bzw. Rückgabewert
  39. einen Typen. Diesen Typen nennen wir \texttt{a} und er ist
  40. vom Typ \texttt{Floating}. Auch \texttt{b}, \texttt{wasweisich}
  41. oder etwas ähnliches wäre ok.
  42. \item[Signatur] Die Signatur liest man am einfachsten von hinten:
  43. \begin{itemize}
  44. \item \texttt{f} bildet auf einen Wert vom Typ \texttt{a} ab und
  45. \item \texttt{f} hat genau einen Parameter \texttt{a}
  46. \end{itemize}
  47. \end{itemize}
  48. \todo[inline]{Gibt es Funktionsdeklarationen, die äquivalent? (bis auf wechsel des namens und der Reihenfolge)}
  49. \subsection{if / else}
  50. Das folgende Beispiel definiert den Binomialkoeffizienten (vgl. \cref{bsp:binomialkoeffizient})
  51. \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/binomialkoeffizient.hs}
  52. \inputminted[numbersep=5pt, tabsize=4]{bash}{scripts/haskell/compile-binom.sh}
  53. \todo[inline]{Guards}
  54. \subsection{Rekursion}
  55. Die Fakultätsfunktion wurde wie folgt implementiert:
  56. \[fak(n) := \begin{cases}
  57. 1 &\text{falls } n=0\\
  58. n \cdot fak(n) &\text{sonst}
  59. \end{cases}\]
  60. \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/fakultaet.hs}
  61. Diese Implementierung benötigt $\mathcal{O}(n)$ rekursive Aufrufe und
  62. hat einen Speicherverbrauch von $\mathcal{O}(n)$. Durch einen
  63. \textbf{Akkumulator}\xindex{Akkumulator} kann dies verhindert werden:
  64. \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/fakultaet-akkumulator.hs}
  65. \subsection{Listen}
  66. \begin{itemize}
  67. \item \texttt{[]} erzeugt die leere Liste,
  68. \item \texttt{[1,2,3]} erzeugt eine Liste mit den Elementen $1, 2, 3$
  69. \item \texttt{:} wird \textbf{cons}\xindex{cons} genannt und ist
  70. der Listenkonstruktor.
  71. \item \texttt{head list} gibt den Kopf von \texttt{list} zurück,
  72. \texttt{tail list} den Rest:
  73. \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/list-basic.sh}
  74. \item \texttt{null list} prüft, ob \texttt{list} leer ist.
  75. \item \texttt{length list} gibt die Anzahl der Elemente in \texttt{list} zurück.
  76. \item \texttt{maximum [1,9,1,3]} gibt 9 zurück (analog: \texttt{minimum}).
  77. \item \texttt{last [1,9,1,3]} gibt 3 zurück.
  78. \item \texttt{reverse [1,9,1,3]} gibt \texttt{[3,1,9,1]} zurück.
  79. \item \texttt{elem item list} gibt zurück, ob sich \texttt{item} in \texttt{list} befindet.
  80. \end{itemize}
  81. \subsubsection{Beispiel in der interaktiven Konsole}
  82. \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/listenoperationen.sh}
  83. \subsubsection{List-Comprehensions}\xindex{List-Comprehension}
  84. List-Comprehensions sind kurzschreibweisen für Listen, die sich an
  85. der Mengenschreibweise in der Mathematik orientieren. So entspricht
  86. die Menge
  87. \begin{align*}
  88. myList &= \Set{1,2,3,4,5,6}\\
  89. test &= \Set{x \in myList | x > 2}
  90. \end{align*}
  91. in etwa folgendem Haskell-Code:
  92. \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/list-comprehensions.sh}
  93. \subsection{Strings}
  94. \begin{itemize}
  95. \item Strings sind Listen von Zeichen:\\
  96. \texttt{tail "ABCDEF"} gibt \texttt{"BCDEF"} zurück.
  97. \end{itemize}
  98. \section{Typen}
  99. In Haskell werden Typen aus den Operationen geschlossfolgert. Dieses
  100. Schlussfolgern der Typen, die nicht explizit angegeben werden müssen,
  101. nennt man \textbf{Typinferent}\xindex{Typinferenz}.
  102. Haskell kennt die Typen aus \cref{fig:haskell-type-hierarchy}.
  103. Ein paar Beispiele zur Typinferenz:
  104. \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/typinferenz.sh}
  105. \begin{figure}[htp]
  106. \centering
  107. \resizebox{0.9\linewidth}{!}{\input{figures/haskell-type-classes.tex}}
  108. \caption{Hierarchie der Haskell Standardklassen}
  109. \label{fig:haskell-type-hierarchy}
  110. \end{figure}
  111. \section{Beispiele}
  112. \subsection{Quicksort}
  113. \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=qsort.hs]{haskell}{scripts/haskell/qsort.hs}
  114. \begin{itemize}
  115. \item Die leere Liste ergibt sortiert die leere Liste.
  116. \item Wähle das erste Element \texttt{p} als Pivotelement und
  117. teile die restliche Liste \texttt{ps} in kleinere und
  118. gleiche sowie in größere Elemente mit \texttt{filter} auf.
  119. Konkateniere diese beiden Listen mit \texttt{++}.
  120. \end{itemize}
  121. Durch das Ausnutzen von Unterversorgung\xindex{Unterversorgung} lässt
  122. sich das ganze sogar noch kürzer schreiben:
  123. \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=qsort.hs]{haskell}{scripts/haskell/qsort-unterversorg.hs}
  124. \subsection{Fibonacci}\xindex{Fibonacci}
  125. \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=fibonacci.hs]{haskell}{scripts/haskell/fibonacci.hs}
  126. \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=fibonacci-akk.hs]{haskell}{scripts/haskell/fibonacci-akk.hs}
  127. \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=fibonacci-zip.hs]{haskell}{scripts/haskell/fibonacci-zip.hs}
  128. \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=fibonacci-pattern-matching.hs]{haskell}{scripts/haskell/fibonacci-pattern-matching.hs}
  129. \subsection{Quicksort}
  130. \subsection{Funktionen höherer Ordnung}
  131. \section{Weitere Informationen}
  132. \begin{itemize}
  133. \item \href{http://hackage.haskell.org/package/base-4.6.0.1}{\path{hackage.haskell.org/package/base-4.6.0.1}}: Referenz
  134. \item \href{http://www.haskell.org/hoogle/}{\path{haskell.org/hoogle}}: Suchmaschine für das Haskell-Manual
  135. \item \href{http://wiki.ubuntuusers.de/Haskell}{\path{wiki.ubuntuusers.de/Haskell}}: Hinweise zur Installation von Haskell unter Ubuntu
  136. \end{itemize}
  137. \index{Haskell|)}