Motivation und Einführung

  • Marco Block-Berlitz
  • Adrian Neumann
Chapter
Part of the Xpert.press book series (XPERT.PRESS)

Zusammenfassung

In der heutigen Zeit müssen wir uns in so vielen Bereichen auf computerbasierte Systeme verlassen, dass es geradezu zwingend notwendig ist, benutzbare, wartbare und fehlerfreie Software zu entwickeln.

Aus diesem Grund sind funktionale Programmiersprachen für den Einstieg in die Programmierung besonders gut geeignet, denn sie verlangen von Programmierern ein hohes Maß an Präzision und ein klares Verständnis für die internen und externen Abläufe.

In der heutigen Zeit müssen wir uns in so vielen Bereichen auf computerbasierte Systeme verlassen, dass es geradezu zwingend notwendig ist, benutzbare, wartbare und fehlerfreie Software zu entwickeln.

Aus diesem Grund sind funktionale Programmiersprachen für den Einstieg in die Programmierung besonders gut geeignet, denn sie verlangen von Programmierern ein hohes Maß an Präzision und ein klares Verständnis für die internen und externen Abläufe.

Darüber hinaus können Programme in funktionalen Programmiersprachen oft sehr kurz und elegant modelliert werden und sich in ihrer Funktionalität auf das Wesentliche konzentrieren. Der Entwickler wird dabei nicht von systemrelevanten Komponenten, wie dem Betriebssystem oder der Hardware, abgelenkt.

Funktionale Programmiersprachen werden in der Praxis genau dort eingesetzt, wo es darum geht, algorithmische Lösungen zu entwickeln, zu verifizieren und zu überprüfen. Im Anschluss werden die Algorithmen oft in höhere, imperative Programmiersprachen, wie Java, C oder C++, übersetzt, da diese doch im Allgemeinen sehr viel weiter verbreitet sind.

1.1 Funktionale Programmierung

Ein Vorteil von funktionalen Programmiersprachen gegenüber anderen ist der hohe Abstraktionsgrad. So wird vom Programmierer verlangt, strikt algorithmisch zu denken und sich speziell was Ein- und Ausgaben betrifft, klar auszudrücken.

Das Besondere an funktionalen Programmiersprachen ist die Tatsache, dass es keine typischen Variablen und Speicherressourcen gibt, sondern nur Funktionen. Das ist zunächst für diejenigen etwas ungewohnt, die sich mit imperativen Programmiersprachen wie C, C++ oder Java, schon auskennen.

Ähnlich wie in Java wird eine strikte Typsicherheit gefordert. Das bedeutet, dass die verwendeten Datentypen für Funktionsergebnisse schon vor dem Programmstart klar spezifiziert sein müssen. Die Entwicklung präziser Programmbeschreibungen im vornhinein erspart eine Typüberprüfung während der Laufzeit eines Programms, vermeidet häufige Fehler und hilft bei der Strukturierung des Programms.

1.1.1 Motivation und Anwendung

Im Vergleich zu anderen Büchern, die lediglich eine Einführung in Haskell versprechen, bietet dieses Buch eine Einführung in die Informatik. Die theoretische Informatik hat gezeigt, dass funktionale Programmiersprachen mit Rekursion genauso mächtig sind wie imperative Programmiersprachen. In einem späteren Kapitel werden wir eine Intuition für diesen Sachverhalt entwickeln.

Der dieser Sprache zugrunde liegende Mechanismus des \( \lambda \)-Kalküls ist mächtig genug, um alle Algorithmen und Technologien darin zu modellieren. Genau das werden wir in diesem Buch unter Beweis stellen und nicht nur die typischen Haskell-Beispiele liefern, sondern neue Methoden aus verschiedenen Informatikdisziplinen modellieren.

1.1.2 Warum gerade Haskell?

Alternativ zu Haskell finden sich viele weitere funktionale Programmiersprachen, wie z.B. Lisp [1.36], Opal [1.41], Meta Language [1.42], Gofer [1.43] oder Miranda [1.44], aber auch Kombinationen aus imperativen und funktionalen, wie z.B. Scala [1.45]. Haskell hat sich gerade in den letzten Jahren in der Lehre vieler Hochschulen etabliert. Es gibt eine ständig wachsende Community und die Sprache wird stetig erweitert.

Die Erfahrungen mit Haskell sind demnach sehr groß. Wir, die beiden Autoren dieses Buches, haben selbst viele Jahre Haskell in der Lehre eingesetzt und sehen einen Bedarf an neuen motivationsfördernden Methoden und Beispielen. Daraus ist auch dieses Buch entstanden.

Im Folgenden wollen wir uns mit einigen Grundbegriffen und Prinzipien der Entwicklung von Programmen vertraut machen, bevor es mit der Installation von Haskell weiter geht.

1.2 Grundbegriffe und Prinzipien der Programmentwicklung

Es ist allgemein bekannt, dass Computer nur „Nullen und Einsen“ verstehen. Wenn wir als Menschen Programme schreiben, wäre es natürlich überaus mühsam, in der Sprache des Computers zu arbeiten. Deswegen wurden Programmiersprachen wie Haskell entwickelt, die die Programmierung auf einer viel höheren Abstraktionsebene erlauben.

Programme werden zunächst als Textdateien in einem Editor wie Notepad++ für Windows [1.46], TextWrangler für Mac OS [1.47] oder Kate für Linux [1.48] geschrieben. Anschließend werden diese Dateien von einem Compiler in Maschinencode übersetzt, der das Programm damit ausführbar macht. Alternativ zum Kompilieren kann ein Interpreter eingesetzt werden, der kein ausführbares Programm erzeugt, sondern den Programmcode live ausführt und die Maschinenbefehle interpretiert. In der Regel ist kompilierter Programmcode in der Ausführung viel schneller als interpretierter Code, da der Compiler viele Optimierungen vornehmen kann, die dem Interpreter nicht möglich sind, und der zusätzliche Aufwand der Interpreterausführung wegfällt.

Lösungen für bestimmte Probleme, wie zum Beispiel das Sortieren einer Liste, werden algorithmisch formuliert. Ein Algorithmus ist ein von der Programmiersprache unabhängiges Rezept zum Lösen des gegebenen Problems, ganz analog zu einem Kochrezept in der Küche. In Abb. 1.1 wird ein Rezept gezeigt, bei dem ein Kuchen in nur \( 5 \) Minuten in der Mikrowelle zubereitet werden kann.
Abb. 1-1

Ein Kuchen in nur 5-Minuten!

Im Laufe dieses Buches werden wir lernen, solche Algorithmen zu entwerfen und zu analysieren.

Eine Datenstruktur stellt eine besondere Art dar, Daten im Speicher geordnet zu halten. So gibt es beispielsweise zwei grundlegende Arten, seine Notizen zu verwalten. Entweder in einem großen ungeordneten Hefter oder alphabetisch sortiert in einem karteikastenähnlichen System. Bei der ersten Variante ist es leicht, eine neue Notiz hinzuzufügen, aber das Auffinden kann dabei sehr lange dauern. Bei der sortierten Aufbewahrung ist der Aufwand beim Einfügen etwas größer, das Wiederfinden ist allerdings sehr viel schneller zu realisieren.

In vielen Algorithmen werden spezielle Datenstrukturen verwendet, um die gegebene Problemlösung zu beschleunigen.

1.3 Installation und Verwendung von Haskell

Um Programme in Haskell erstellen zu können, ist eine Entwicklungsumgebung notwendig. Es kann sich dabei um einen einfachen Texteditor handeln oder um ein komplexeres Werkzeug, das bereits während der Programmerstellung unterstützen kann.

Des Weiteren wird ein Interpreter bzw. Compiler benötigt, der die vorhandenen Programmzeilen vor der Ausführung auf Korrektheit überprüft und anschließend entsprechend interpretiert und ausführt.

1.3.1 Installation der aktuellen Version

Es gibt, wie bei anderen Programmiersprachen ebenfalls üblich, eine ganze Reihe von möglichen Interpretern und Entwicklungsumgebungen. Das Buch möchte keine Bewertung der vorhandenen Produkte vornehmen, sondern dem Leser lediglich einen möglichen Weg aufweisen, um die funktionale Programmiersprache Haskell zu erlernen und anzuwenden.

Um die bekanntesten Betriebssysteme Windows, Linux und Mac OS abzudecken, wurde für das Buch der Hugs-Interpreter ausgewählt. Auf der Webseite

http://www.haskell.org/hugs/

stehen die verschiedenen Versionen zum Download bereit. Zusätzlich ist die Seite

http://www.haskell.org

sehr interessant, da auf Veranstaltungen, weiterführende Literatur und aktuelle Arbeiten der ständig wachsenden Haskell-Community verwiesen wird.

Alternativ kann beispielsweise der Glasgow Haskell Compiler (GHC) verwendet werden [1.39]. Im Gegensatz zu Hugs ist dieser ein vollständiger Compiler, der ausführbare Programme erzeugt. Er stellt aber auch einen Interpreter zur Verfügung, dessen Verwendung sich von Hugs kaum unterscheidet. GHC wird ständig weiter entwickelt und enthält viele experimentelle Spracherweiterungen, die im Haskellstandard noch nicht vorgesehen sind. Für die Zwecke unseres Buches ist Hugs vollkommen gleichwertig und wird von uns aufgrund der etwas leichteren Handhabung für alle Beispiele verwendet.

Nachdem die Installationsdateien herunter geladen wurden, werden diese gestartet. Im Falle von Windows, wird ein Installationspfad angegeben, zum Beispiel *C:\Program Files\WinHugs, in dem alle notwendigen Dateien gespeichert werden.

Wenn keine Verknüpfung zu WinHugs auf dem Desktop angelegt wurde, lässt sich die ausführbare Datei *winhugs.exe in dem Installationsordner finden: * C:\Program Files\WinHugs>dir 06.11.2008 10:18 <DIR> . 06.11.2008 10:18 <DIR> .. 05.11.2008 14:58 <DIR> demos 06.11.2008 10:18 <DIR> docs 06.11.2008 10:18 269 ffihugs.bat 06.11.2008 10:18 520.192 ffihugs.exe 06.11.2008 10:18 532.480 hugs.exe 06.11.2008 10:18 <DIR> include 06.11.2008 10:18 63.043 install.log 06.11.2008 10:18 <DIR> oldlib 05.11.2008 14:58 <DIR> packages 05.11.2008 14:58 <DIR> programs 06.11.2008 10:18 2.349 readme.txt 06.11.2008 10:18 520.192 runhugs.exe 06.11.2008 10:18 62.237 uninstaller.exe 06.11.2008 10:18 634.880 winhugs.exe 8 File(s) 2.335.642 bytes 8 Dir(s) 5.967.183.872 bytes free

Für das vorliegende Buch wird die Hugs-Version vom September \( 2006 \) verwendet. Als gute Alternative bietet sich noch die an der Universität Utrecht entwickelte Umgebung Helium an [1.49].

Der folgende Abschnitt wird einen Überblick zu den vorhandenen Hugs-Komponenten liefern.

1.3.2 Die ersten Schritte in Hugs

Der Aufbau des Haskellsystems ist im Gegensatz zu anderen Programmiersprachen sehr überschaubar. Zunächst wollen wir Haskell für kleine Tests in der Konsole kennenlernen und anschließend die mitgelieferte Entwicklungsoberfläche *winhugs starten.

Exemplarisch werden wir das Betriebssystem Windows verwenden. Im weiteren Verlauf des Buches ist es allerdings egal, welches Betriebssystem eingesetzt wird.

1.3.3 Arbeiten auf der Konsole

Im Installationsverzeichnis von Hugs befindet sich die ausführbare Datei *hugs.exe. Nach dem Start des Programms in einer Konsole erhalten wir: * C:\Program Files\WinHugs>hugs __ __ __ __ ____ ___ _________________________________________ || || || || || || ||__ Hugs 98: Based on the Haskell 98 standard ||___|| ||__|| ||__|| __|| Copyright (c) 1994-2005 ||___|| ___|| World Wide Web: http://haskell.org/hugs || || Bugs: http://hackage.haskell.org/trac/hugs || || Version: 20051031 _________________________________________ Type :? for help Hugs>

Eine Möglichkeit mit dem Hugs-System zu arbeiten, ist die Verwendung der Konsole. Nach dem Start des Haskell-Interpreters erwartet das System eine Eingabe nach dem Prompt *Hugs&gt;.

Wird beispielsweise die Hilfe mit *:? aufgerufen, so werden die wichtigen Systemfunktionen angezeigt: * :load <filenames> load modules from specified files :load clear all files except prelude :also <filenames> read additional modules :reload repeat last load command :edit <filename> edit file :edit edit last module :module <module> set module for evaluating expressions <expr> evaluate expression :type <expr> print type of expression :? display this list of commands :set <options> set command line options :set help on command line options :names [pat] list names currently in scope :info <names> describe named objects :browse <modules> browse names exported by <modules> :main <aruments> run the main function with the given arguments :find <name> edit module containing definition of name :cd dir change directory :gc force garbage collection :version print Hugs version :quit exit Hugs interpreter

Die Konsole lässt sich jetzt erst einmal als Eingabe für einen Taschenrechner verwenden, so können beispielsweise einfache Rechenoperationen ausgeführt werden: * Hugs> 4+3 7 Hugs> -17*21 -357

Es können so beliebig komplexe Ausdrücke eingegeben und ausgewertet werden. Das Programm wird schließlich mit der Eingabe *:quit beendet.

1.3.4 Die Entwicklungsumgebung winhugs

Etwas mehr Komfort für die Verwendung von Haskell mit dem Hugs-Interpreter bietet das Programm *winhugs.exe. Nach dem Start erscheint eine Oberfläche, die einige Funktionen zur Verfügung stellt (s. Abb. 1.2).
Abb. 1-2

Grafische Oberfläche von *winhugs

Die Konsole, die wir in dem vorhergehenden Abschnitt kennengelernt haben ist jetzt in ein Fenster eingebettet und kann entsprechend verwendet werden.

1.3.5 Erstellung und Verwendung von Skripten

Haskell bietet zwei Formatvarianten an, um Programme zu schreiben. Wenn der Umfang des Programmcodes im Vergleich zu den Kommentaren größer ist, dann ist es sinnvoll und weniger aufwändig, die Kommentare zu markieren und den Rest als Programm zu interpretieren: * – Kommentarzeile f x = 2*x g x = x+19

In der ersten Zeile steht ein Kommentar. Dieser wird mit vorangesetztem „ *- -“ markiert. Nach dem „ *- -“ sollte ein Leerzeichen oder ein Buchstabe folgen, da es möglich ist, Zeichenfolgen wie „ *- -+“ später als Operator zu verwenden. Die Skriptform lässt sich durch die Dateiendung **.hs für haskell script angeben.

Angenommen es existiert eine Datei *skript.hs mit dem obigen Inhalt im Verzeichnis *C:\, dann können wir dieses Skript mit dem Befehl *:load oder kurz *:l in der Konsole laden. Alternativ lässt sich das Skript unter *winhugs mit *File/Open laden: * Hugs> :l c:\skript.hs Hugs> f 10 20

Wir haben das Skript geladen und sogar eine der beiden vorhandenen Funktionen aufgerufen. Die Funktion *f soll für eine Eingabe *x den doppelten Wert zurückliefern und tut das auch, wie es im Beispiel zu sehen ist.

Sollte der Kommentarteil größer als der Programmcodeteil sein, werden entsprechend die Programmzeilen markiert. In diesem Fall mit dem Symbol , *&gt;‘. * Es folgt eine Funktion f, die das Quadrat der Eingabe x zurückliefert: > f x = x*x

Wichtig dabei ist, dass zwischen den Kommentarzeilen und den Programmzeilen mindestens eine freie Zeile verbleibt. Dieses Skriptformat wird mit der Dateiendung **.lhs für literate haskell script gespeichert.

1.4 Haskell ist mehr als ein Taschenrechner

Bisher haben wir Haskell als Taschenrechner kennengelernt. Es wird ein Funktionsausdruck eingegeben und daraus folgt die Rückgabe eines Ergebnisses. Die Funktionalität ist mit der eines Standardtaschenrechners aber nicht vergleichbar.

Da Haskell eine Programmiersprache ist, sind den Anwendungsmöglichkeiten nur wenig Grenzen gesetzt. So gibt es beispielsweise Haskellprojekte mit OpenGL-Anbindung (s. Abb. 1.3) [1.53,1.54].
Abb. 1-3

Links: Frag, ein in Haskell entwickelter Egoshooter (Abb. aus [1.53]). Rechts: Monadius, ein Raumschiffspiel (Abb. aus [1.54])

Eine große Sammlung von Projekten aus verschiedenen Gebieten, wie z.B. Datenbanken, Datamining, Grafik oder Mustererkennung, findet sich unter [1.52].

Das vorliegende Buch liefert eine Einführung in die Informatik mit der funktionalen Programmiersprache Haskell. Der Fokus liegt dabei auf einer Ausbildung mit akademischem Ansatz. Da Haskell aber auch in der Praxis durchaus eine wichtige Rolle spielt und aktuelle Technologien, wie beispielsweise Webanwendungen, Client-Server-Architekturen oder Datenbankanwendungen, realisiert werden können, wollen wir dem Leser als Folgeliteratur das Buch von O’Sullivan, Goerzen und Stewart empfehlen [1.1].

1.5 Vordefinierte Funktionen der Prelude

Damit wir nicht bei Null beginnen müssen, ist das Haskellsystem bereits zu Beginn schon mit einer großen Bibliothek ausgestattet. Diese heißt *Prelude.hs und befindet sich im Hugs-Installationsordner (s. Abb. 1.4).
Abb. 1-4

Unter *winhugs lassen sich die geladenen Bibliotheken anzeigen (File/Module Manager)

Beim Start wird sie automatisch geladen, damit die grundlegenden Funktionen, wie beispielsweise *+, * -, * * und */, zur Verfügung stehen. Die Operationen eines Taschenrechners, wie wir sie bereits verwendet haben, lassen sich als Funktionen darstellen und wie es für Funktionen üblich ist in Präfixschreibweise notieren.

So liefern die beiden Ausdrücke *4+9 und *(+) 4 9das gleiche Ergebnis. Testen wir das in der Konsole: * Hugs> 4+9 13 Hugs> (+) 4 9 13

Die Addition ist dabei als Funktion zu verstehen, die zwei Eingaben benötigt und ein Ergebnis liefert. Jede Operation lässt sich als Funktion interpretieren und aufschreiben, aber dazu später mehr.

In den folgenden Kapiteln werden wir neben den grundlegenden Konzepten einige dieser Bibliotheksfunktionen besser kennenlernen und damit beginnen, erste kleine Haskellprogramme zu entwerfen.

Copyright information

© Springer Berlin Heidelberg 2011

Authors and Affiliations

  • Marco Block-Berlitz
  • Adrian Neumann
    • 1
  1. 1.Universität des SaarlandesSaarbrückenDeutschland

Personalised recommendations