Seminar: Fortgeschrittene Konzepte der funktionalen Programmierung Sommersemester 2015 Agda Marcel Lotze Technische Universität München Fakultät für Informatik 03.06.2015 Agda ist eine funktionale Programmiersprache, die an der TH Chalmers und der Universität von Götheborg entwickelt wurde. Sie setzt die Konzepte der von Martin-Löf formulierten intuitionistischen Typentheorie um. Ein korrekt in Agda implementiertes Programm zeigt gleichzeitig die Lösbarkeit eines zugrundeliegenden Problems, weswegen Agda tatsächlich als Beweisassistent verwendet wird. Diese Ausarbeitung soll einen Überblick über Agda, die intuitionistische Typentheorie, auf der Agdas Typsystem basiert, sowie die in Agda implementierte Homotopietypentheorie geben. Zunächst soll jedoch die Sprache selber vorgestellt werden. 1 Einleitung Das Konzept der funktionalen Sprache Agda soll in Abschnitt 2 vorgestellt werden. Es werden dort Beispiele gegeben, welche die Kernkonzepte, die Agda von anderen Sprachen wie Haskell oder OCaml unterscheiden, verdeutlichen sollen. Das betrifft vor Allem sogenannte dependent types, Typen, die mit anderen Typen und Variablen parametrisiert werden können. Agda wird tatsächlich nicht primär als Sprache zur Erzeugung von ausführbarem Code, sondern als Beweisassistent eingesetzt. Das Typsystem von Agda basiert auf der Typentheorie von Martin-Löf. In dieser Typentheorie wird alles Konstruierbare als wahr angesehen, daher können Lemmata bspw. durch ihre Formulierung als Typ und die Konstruierbarkeit dieses Typs gezeigt werden. Entsprechend des Curry-Howard-Isomorphismus zeigen korrekt in Agda implementierte Programme die Lösbarkeit eines Problems, was äquivalent zu einem Beweis der dem Problem entsprechenden Proposition ist [1, S. 6 ff.]. Die entsprechenden Theorien und ihre Umsetzung in Agda werden in Abschnitt 3 vorgestellt. Anhand von kurzem Beispielcode wird dort die Nutzung von Agda als Beweisassistent gezeigt. Agda bietet die Möglichkeit, mit dem Typechecker zu interagieren und die Programmierung bzw. die Beweisführung so interaktiv zu gestalten. Dies, und weitere Techniken und Werkzeuge der praktischen Arbeit mit Agda sollen in Abschnitt 4 vorgestellt werden. 1 2 Sprachkonzepte Die erste Fassung der Programmiersprache Agda wurde an der Universität von Götheborg 1999 von Coquand und Coquand entwickelt [5]. Ihre Arbeit fokussierte sich damals darauf, eine funktionale Programmiersprache zu entwerfen, die auf der strukturierten Typentheorie fußt. Letztere bezeichnet ein einfaches Typsystem, das unter anderem um lokale Definitionen ergänzt wurde. Im Jahr 2007 hat Norell im Rahmen seiner Dissertation [13] die Sprache Agda so weiterentwickelt, dass sie nunmehr dependent types, Typen, die mit anderen Typen und Variablen parametrisiert werden können, einführt. Seine Implementierung von Agda basiert auf der von Martin-Löf formulierten intuitionistischen Typentheorie, in der dependent types, wie in Abschnitt 2.2 vorgestellt, existieren [13, S. 13]. Genauer basiert das Typsystem von Agda nach Norell auf der intuitionistischen Typentheorie. Diese Theorie versucht eine Grundlage zur Formulierung mathematischer Grundlagen zu schaffen, es handelt sich also um eine konstruktivistische Theorie. Der Intuitionismus ist eine Denkrichtung, in der Konstruierbares als wahr und entsprechend Nichtkonstruierbares als falsch angesehen wird [2, S. 25]. Agdas Typsystem bietet einen Rahmen zur Definition von Typen und Funktionen. Es existieren umfangreiche Bibliotheken zur Benutzung in Agda, in denen Zahlenräume, Operatoren etc. vordefiniert sind [4, Eintrag Standard libraries]. Nichtsdestotrotz ist es genauso möglich, ohne Bibliotheken mit Agda zu arbeiten. Zahlenräume, Operatoren und deren Eigenschaften wären dann bspw. vom Nutzer zu definieren. Das Typsystem ist dabei so ausgelegt, dass eine korrekte Implementierung gleichzeitig als Beweis für eine Proposition gelten kann [17, S. 1 ff.], wie später noch ausführlich erläutert. Alle benötigten Theoreme, wie bspw. die Kommutativität der Addition [1, S. 5], müssen in Agda explizit gezeigt werden, bevor sie verwendet werden können. Die Syntax von Agda erinnert stark an Haskell, Leerzeichen und Einrückungen werden zur Gliederung des Programmtextes verwendet. Dabei gibt es nur eine sehr kleine Menge von Schlüsselwörtern [13, S. 98] und reservierten Symbolen, wie runden und geschweiften Klammern [14, S. 4]. Alle weiteren Symbole sind zulässig zur Benennung von Datentypen, Funktionen etc., wobei der Unterstrich als Platzhalter für die Definition von In- und Mixfixoperatoren reserviert ist, siehe Listing 1. data Bool : Set where true : Bool false : Bool if_then_else : { A : Set } → Bool → A → A → A if true then a else _ = a if false then _ else b = b Listing 1: Definition von if-then-else als Mixfixoperator. Erkennbar wird im gezeigten Beispiel der Unterstrich als Platzhalter bei der Definition von Operatoren verwendet. Erklärungsbedürftig sind an dieser Stelle zwei weitere Besonderheiten von Agda: Zum einen der Typ Set des Datentyps Bool, der im folgenden Abschnitt erklärt wird. Zum anderen der implizite Parameter {A : Set}. if-then-else wurde hier als polymorphe Funktion definiert, die zwei Ausdrücke des Typs A als Parameter entgegennimmt. Dabei kann der Typ einerseits ebenfalls als expliziter Parameter übergeben werden, was durch eine runde Klammerung angegeben würde, oder wie in diesem Falle implizit über die explizit anzugebenen Ausdrücke ermittelt werden. Implizite Parameter müssen nur dann zwangsläufig angegeben werden, wenn ihre Verwendung in der Definition 2 notwendig ist. Implizite Parameter [13, S. 26] spielen nicht nur bei der gezeigten Polymorphie nach Parametertypen eine Rolle, sondern auch bei den sogenannten dependent types, wie in Unterabschnitt 2.2 erläutert. Dies ist eine Folge der Tatsache, dass in Agda nicht strikt zwischen Typen und Werten unterschieden wird, wie von Norell in [14, S. 1 ff.] erläutert. Gut erkennbar ist auch das pattern matching in der Definition von if-then-else. Das pattern matching in Agda wurde um einige nützliche Konzepte wie Wildcards oder Bedingungen für die gematchten“ ” Werte (mit dem with-Konstrukt, [14, S. 13]), wie sie aus Haskell bekannt sind, erweitert. 2.1 Der Typ Set Nicht-parametrisierte Datentypen wie beispielsweise der in Listing 1 gezeigte Datentyp Bool sind vom Typ Set. Parametrisierte Datentypen (”dependent types”) sind vom Typ Setn , wobei n um eins größer ist als das Maximum von m0 ... mi der Typen Setm0 ... Setmi der Parameter (0 bis i). Dass alle Typen in Agda vom Typ Set, also Menge sind, ist eine Konsequenz daraus, dass das Typsystem von Agda auf der Typentheorie von Martin-Löf aufbaut. In dieser Theorie werden Typen mit Mengen gleichgesetzt, während Elemente einer Menge gleichzeitig von diesem Typ sind [17, S. 2 f.]. Bei parametrisierten Typen, die also in Set1..n liegen, entfällt die explizite Angabe von Setn als Typ, dies ergibt sich wie beschrieben bereits aus den jeweiligen Parametern. Es gibt eine endlose Hierarchie von größer werdenden Universen [3, S. 74], die nach dem oben beschriebenen Prinzip eine Menge von Typen enthalten. Alle Typen die vom Typ Set wären bilden ein Universum und Typen die nach dem oben beschriebenen Prinzip zu Setn gehören, bilden jeweils ein Universum. Listing 2 zeigt ein kurzes Beispiel für die praktische Relevanz in Agda. data Bool : Set where true : Bool false : Bool { - Bool ist wie definiert vom Typ Set -} data Kapsel : ( A : Set ) → Set where { - Kapsel ist vom Typ Set → Set, da der Parameter als vom Typ Set definiert wurde . Set → Set ist vom Typ Set1 . -} Listing 2: Abhängig von ihrer Parametrisierung sind Datentypen selber verschiedenen Typs. 2.2 Dependent types Agda wurde so konzipiert, dass das Typsystem die intuitionistische Typentheorie, auch Martin-Löf Typentheorie genannt, umsetzt. Selbige wird später im Abschnitt 3.1 weitergehend beschrieben. In dieser Theorie existieren dependent types, Typen, welche polymorph sind und/oder von Variablen abhängen. In Agda ist es entsprechend möglich, Datentypen zu definieren, deren Definition von Variablen abhängt [1, S. 2]; prominente Beispiele hierfür sind, wie in Listing 3 gezeigt, Vektoren bzw. Listen der Länge n, wobei n ∈ N. In Listing 3 wird die Implementierung eines dependent type in Agda demonstriert. In diesem Beispiel zeigt sich insbesondere, dass bei Parametern von dependent types nicht zwischen Werten und Typen unterschieden wird. Bei der Instanziierung eines Objekts 3 können diese explizit oder implizit übergeben, und beim Zugriff auf ein Objekt genauso entweder explizit übergeben oder inferiert werden. In [14] werden polymorphe Datentypen, die noch mit einer Variablen indiziert sind, als mit einer Variable indizierte datatype families bezeichnet. In Listing 3 ist IndizierteListe mit einer natürlichen Zahl indiziert, welche die momentane Länge der Liste ab einem Element angibt. Parametrisiert wurde IndizierteListe mit einem Typ A, der für alle Instanzen von IndizierteListe (welche hier rekursiv definiert ist) gleich ist. Der Index hingegen ist für jede Instanz verschieden. Die Funktion LängeDerListe im Listing macht ein pattern matching gegen die impliziten wie expliziten Parameter der Funktion. Implizite Parameter werden in Agda in geschweifte Klammern gesetzt - ihr Wert kann aus anderen, explizit übergebenen Parametern inferiert werden. Im Falle von LängeDerListe ist n ein impliziter Parameter, der aus der Länge n der explizit zu übergebenen IndiziertenListe abgeleitet wird. data VerketteteListe ( A : Set ) : Set where Ende : A → VerketteteListe A Elem : A → ( V : VerketteteListe A ) → VerketteteListe A { - VerketteteListe ist ein " dependent type " mit Parameter Typ A ; ein polymorpher Datentyp -} data N : Set where null : N nachf : N → N data IndizierteListe ( A : Set ) : N → Set where Ende : A → IndizierteListe A null Elem : { n : N} → A → IndizierteListe A n → IndizierteListe A ( nachf n ) { - Indizierte Liste ist wie VerketteteListe ein polymorpher Datentyp , allerdings tr ä gt diese Liste noch einen Index f ü r das aktuelle Element . -} L ä ngeDerListe : { A : Set }{ n : N} → IndizierteListe A n → N L ä ngeDerListe { _ } { n } _ = nachf n { - Der Index wird beim Pattern Matching dann h ä ufig als impliziter Parameter genutzt . Er wird vom tats ä chlich ü bergebenen Objekt inferiert . -} Listing 3: Sowohl Typen als auch Variablen können Parameter eines Datentyps sein. 2.3 Modulsystem Das Modulsystem von Agda erinnert zunächst an jenes von Haskell: Der Inhalt einer Datei kann als Modul gekapselt werden, dabei können einzelne Elemente versteckt werden; auch public/private Sichtbarkeitsbeschränkungen existieren. Die Besonderheit des Modulsystems von Agda liegt in der Parametrisierbarkeit von Modulen: Module können mit Typen parametrisiert werden, wobei im entsprechenden Modul enthaltene Funktionen die Parameter als Argumente entgegennehmen [14, S. 17]. Wird ein Modul instanziiert, so müssen die Parameter mit übergeben werden, und enthaltenen Funktionen werden diese als Argumente bereitgestellt, d.h. sie müssen beim Aufruf einer Funktion eines instanziierten Moduls nicht erneut angegeben werden. Die Parametrisierung 4 erfolgt explizit. Listing 4 zeigt ein mit einem Typ parametrisiertes Modul. Der Parameter wird weiterhin im Modul verwendet. In Listing 5 ist zu sehen, wie das Modul wiederverwendet und als Parameter der Typ N übergeben wird. Den im parametrisierten Modul enthaltenen Typen und Funktionen wird ebenfalls entsprechend der Typ N übergeben. module Modul ( A : Set ) where data Tupel : A → A → Set where tupel : ( a : A ) → ( b : A ) → Tupel a b private data VersteckterTyp : Set where Listing 4: In einem Modul können Inhalte versteckt werden und Module können auch parametrisiert werden. module Anderes where data N : Set where null : N nachf : N → N open import Modul N renaming ( Tupel to NTupel ) { - Erkl ä rung : M odul N ü bergibt den Typ als Parameter an das Modul import wird ben ö tigt , wenn ein Modul in einer externen Datei liegt Bei Nutzung von open entf ä llt die Angabe des Modulnamenspr ä fixes ( Sonst m ü sste bspw . M odul.T upel genutzt werden ) renaming benennt Teile des Moduls um , so k ö nnen evtl . N am e n sr a u mk o n f li k t e verhindert werden -} bspTupel = tupel null ( nachf null ) { - bspTupel ist vom Typ NTupel , entsprechend der Umbenennung -} { - Der Ausdruck " etwas = VersteckterTyp " w ü rde einen Fehler erzeugen , da VersteckterTyp nicht sichtbar ist -} Listing 5: Dieses Listing zeigt den Import eines externen Moduls 3 Agda als Beweisassistent Im vorherigen Abschnitt wurden die grundlegenden Konzepte der Sprache Agda vorgestellt. Im Folgenden soll nun darauf eingegangen werden, wie Agda als Beweisassistent verwendet werden kann. Dies betrifft nicht so sehr die praktischen Aspekte der Arbeit mit Agda, die erst später erläutert werden, sondern vielmehr Theorien, auf deren Basis Beweise geführt werden können. Zunächst soll die intuitionistische Typentheorie, auf der das Typsystem von Agda basiert, vorgestellt werden. Anschließend soll die Homotopietypentheorie 5 vorgestellt werden, eine Theorie, die als Bibliothek für Agda formuliert wurde und auf Basis derer ebenfalls Beweise geführt werden können. 3.1 Intuitionistische Typentheorie Wie bereits vorhergehend erwähnt wurde die intuitionistische Typentheorie von MartinLöf formuliert. Die Typentheorie ist als grundlegender Rahmen“ [12, S. 2] zur Kon” struktion mathematischer Sachverhalte zu verstehen; sie kann konstruktivistisch genutzt werden, um mathematische Grundlagen zu formulieren. Tatsächlich kann die intuitionistische Typentheorie selbst als funktionale Sprache angesehen werden [17, S. 1] und Agda ist eine Implementierung beziehungsweise eine Umsetzung dieser Sprache [13, S. 4, 97]. In der intuitionistischen Typentheorie werden Mengen als Typen angesehen [17, S. 3]. Die Menge der natürlichen Zahlen würde also als der Typ natürliche Zahl“ angesehen. ” Elemente können dann diesen Typs sein, ein Elemente der Menge der natürlichen Zahlen wäre also vom Typ natürliche Zahl“. In der intuitionistischen Typentheorie gibt es ins” besondere dependent types, wie vorhergehend für die Sprache Agda vorgestellt. Der Curry-Howard-Isomorphismus bezeichnet, bezogen auf die intuitionistische Typentheorie, die Beobachtung, dass wenn Typen als Propositionen angesehen werden, Objekte dieser Typen als Beweise für ebendiese gelten können [16, S. 78 f.] [17, S. 1]. Martin-Löf bezieht sich in [10, S. 5] unter anderem auf die Aussagen von Curry und beschreibt, dass in seiner Theorie folgende äquivalente Aussagen gelten: • A ist eine Menge und a ist Element dieser Menge. Dann ist A nicht leer. • A ist eine Proposition und a ist ein Beweis von A. Dann ist A wahr. • A ist ein Problem und a ist eine Lösungsmethode für A. Dann ist A lösbar. Unter Ausnutzung dieses Isomorphismus wird Agda in der Praxis als Beweisassistent verwendet. Theoreme lassen sich als Typen in Agda in formulieren. Rekursive Definitionen in Agda müssen in jedem Fall terminieren. Damit diese Terminierung gezeigt werden kann, muss ein Argument beim rekursiven Aufruf in der Definition kleiner werden. Da mit dieser Bedingung alle Funktionen in Agda terminieren, lässt sich deren Korrektheit per Induktion zeigen. Die Implementierung von reellen Zahlen in Agda ist möglich [15, S. 15 ff.], aber beispielsweise Operationen mit reellen Zahlen, die nicht notwendigerweise terminieren, können in Agda nicht implementiert werden. Aus der obigen Aufzählung ergibt sich auch, dass in der Typentheorie von Martin-Löf Typen und Propositionen äquivalent sind. Lemmata können also beispielsweise durch korrekte Formulierung als Typ in Agda gezeigt werden. 3.2 Homotopietypentheorie Die Homotopietypentheorie wurde am Institute for Advanced Studies im Jahr 2012 formuliert [6, S. 1]. Sie ist eine Theorie, welche die Typentheorie von Martin-Löf mit der Homotopietheorie zu vereinen versucht. Wie auch die Typentheorie von Martin-Löf soll diese Theorie eine Grundlage zur Formulierung und zum Beweisen mathematischer Sachverhalte bilden, d.h. es handelt sich um konstruktivistische Theorien [6, S. 1 f.]. Es existiert eine Implementierung der Homotopietypentheorie als Bibliothek für Agda [8]. Die Bibliothek definiert Axiome, Typen und Operatoren der Homotopietypentheorie und beinhaltet einige Lemmata, so dass Beweise 6 auf Basis dieser Theorie formuliert werden können. Eine solche Bibliothek existiert auch für den Theorembeweiser Coq, geschrieben in OCaml. Ein Typ entspricht in der Homotopietheorie einem Raum, während ein Objekt einem Punkt in diesem Raum entspricht. Zwei Objekte sind äquivalent, wenn ein Pfad zwischen ihren Punkten existiert. In der Homotopietypentheorie existiert ebenfalls ein Äquivalent zu dependent types, die Faserungen. Die Homotopietheorie soll an dieser Stelle nicht weiter erörtert werden, weiterführende Erklärungen zur Homotopietheorie finden sich bspw. in [7, S. 375]. Der interessante Aspekt ist, dass die Homotopietypentheorie auf Basis des Typsystems von Agda als Bibliothek formuliert werden konnte und mit Nutzung dieser Bibliothek wiederum Beweise auf Basis der Homotopietypentheorie in Agda formuliert werden können. Beispiel Die folgenden Beispiele sollen nun zeigen, wie sich in der intuitionistischen Typentheorie bzw. der Homotopietypentheorie formulierte Aussagen in Agda schreiben lassen. Dabei wird zunächst ein Sachverhalt nach der in [17] bzw. [18] verwendeten Sprache in der Typentheorie, anschließend in Agda formuliert. Intuitionistische Typentheorie (ITT) W T yp, w ∈ W, W nicht leer, U T yp, U leer P =W,Q=W P ∧Q=W , (P ∧ Q = W ) → (P = W ), (P ∧ Q = W ) → (Q = W ) ITT in Agda data Unwahrheit : Set where data Wahrheit : Set where wahr : Wahrheit data _∧_ ( P Q : Set ) : Set where _UND_ : P → Q → P ∧ Q beweise∧1 : { P Q : Set } → ( P ∧ Q ) → P beweise∧1 ( P UND Q ) = P beweise∧2 : { P Q : Set } → ( P ∧ Q ) → Q beweise∧2 ( P UND Q ) = Q Augenfällig ist die Modellierung von Wahrheit und Unwahrheit. Wahrheit ist in diesem Fall die Menge mit genau einem ohne Argumente konstruierbaren Element, Unwahrheit die Menge ohne konstruierbares Element [11, S. 297]. Die Modellierung kommt aus der intuitionistischen Typentheorie und stellt in Agdas Typsystem tatsächlich Wahrhheit und Absurdität dar (analog in der Homotopietypentheorie), wobei die Wahrheit durch Mengen mit konstruierbaren Elementen repräsentiert wird. Vorherige Modellierungen als Boolsche Variablen stellten tatsächlich nur Konstruktoren in einem algebraischen Datentyp, ohne ungewöhnliche Bedeutung im Typsystem dar. Nach [1] wird hier die Konjunktion als Typ modelliert und deren Gültigkeit anschließend gezeigt. Da A ∧ B nur in genau einem Fall, wenn sowohl A als auch B wahr sind, wahr ist, kann die Korrektheit gezeigt werden, indem A ∧ B → A und A ∧ B → B gezeigt werden. 7 Homotopietypentheorie (HoTT) W Raum, w ∈ W, W nicht leer, U Raum, U leer P 'W,Q'W P ∧Q'W , (P ∧ Q ' W ) → (P ' W ), (P ∧ Q ' W ) → (Q ' W ) HoTT in Agda open import HoTT data Unwahrheit : T ype0 where data Wahrheit : T ype0 where wahr : Wahrheit data _∧_ ( P Q : T ype0 ) : T ype0 where _UND_ : P → Q → P ∧ Q beweise∧1 : { P Q : T ype0 } → ( P ∧ Q ) → P beweise∧1 ( P UND Q ) = P beweise∧2 : { P Q : T ype0 } → ( P ∧ Q ) → Q beweise∧2 ( P UND Q ) = Q Sowohl die Implementierung in Agda, als auch die Formulierung in der Homotopietypentheorie ähneln dem vorherigen Beispiel aus der intuitionistischen Typentheorie; allerdings werden Wahrheit und Unwahrheit hier als Räume, nicht als Typen betrachtet. Diese Räume entsprechen jedoch Typen, weshalb in der HoTT-Bibliothek für Agda, auch zur Unterscheidung von Set, der Typ Set in Type umbenannt wurde, wobei T ype0 =Set ˆ und T ypen =Set ˆ n für n > 0. Die Äquivalenz von zwei Typen wird in der HoTT, wie in [9, S. 5] beschrieben, als A ' B geschrieben. 4 Arbeiten mit Agda Nachdem nun die Konzepte der Sprache Agda und die Verwendung von Agda als Beweisassistent vorgestellt wurden, sollen im folgenden Abschnitt Techniken und Werkzeuge vorgestellt werden, welche für die praktische Arbeit mit Agda, insbesondere für die Beweisführung in Agda, relevant sind. 4.1 Compiler und Editor Agda selber ist in Haskell implementiert [13, S. 97] und kompiliert auch in diese Sprache, d.h. Agda wird plattformunabhängig zu Haskellcode kompiliert. Ähnlich OCaml kann Emacs als Editor für Agda verwendet werden, dabei werden aktive Buffer an den Compiler bzw. Typechecker übergeben und Feedback des Compilers wird nicht nur textuell, sondern auch visuell im Code (durch farbliche syntaktische Hervorhebungen) dargestellt. Es ist auch möglich, spezielle Funktionen des Typecheckers für einen bestimmten Bereich des Buffers in Emacs aufzurufen, beispielsweise die Anzeige des Typs eines Elements im Code. Die TH Chalmers unterhält eine Projektseite zur Entwicklung von Agda [4]. 8 4.2 Holes Bei der Programmierung in Agda können an geeigneten Stellen sogenannte holes [13, S. 98] mit einem Fragezeichen (?) oder in geschweiften Klammern mit Ausrufezeichen ({!}) gesetzt werden. An diesen Stellen wird der Typechecker von Agda zurückgeben, welchen Typs ein dort erwarteter Ausdruck sein müsste. Auf diese Art und Weise können Codestücke wie beispielsweise Lemmata interaktiv vervollständigt werden. Geeignete Stellen sind unter anderem linke wie rechte Seiten im pattern matching oder Stellen in Definitionen, bei denen der Definitionstyp schon gegeben ist und an denen Ausdrücke erwartet würden. Ein Beispiel hierfür findet sich in Listing 6. data Bool : Set where true : Bool false : Bool _∧_ : Bool → Bool → Bool true ∧ true = true _ ∧ _ = ? _ ∧ _ = { }0 { - Der Typechecker ersetzt , wenn m ö glich , das Hole durch eine nummerierte Anmerkung -} ?0: Bool { - Und gibt auf der Konsole den erwarteten Typ dazu aus -} Listing 6: Für sogenannte holes gibt der Typechecker wenn möglich den an der Stelle erwarteten Typ aus. 4.3 postulate Mit dem Schlüsselwort postulate können Elemente eines Typs axiomatisch postuliert werden, ohne dass deren tatsächliche Definition gegeben wird [4, Eintrag postulate]. So ist es zwar möglich, Axiome aufzustellen, allerdings werden diese nicht weiter durch den Typechecker von Agda überprüft. Im in Listing 7 gezeigten Beispiel wird die Existenz von Primzahlen vom Typ N postuliert. Agda nimmt die Existenz und Konstruierbarkeit als gegeben an, ohne dass eine konkrete Implementierung gegeben wird. data N : Set where null : N nachf : N → N postulate Primzahlen : N Listing 7: Mit postulate können Elemente eines Typs axiomatisch festgelegt werden. 4.4 Absurd pattern Kommt beim pattern matching ein Pattern vor, für das kein Ausdruck auf der rechten Seite gefunden werden kann (beispielsweise bei der Division durch Null), dann kann das sogenannte absurd pattern verwendet werden. Agda prüft die Erschöpfung eines Patterns anhand der geforderten Typen auf der linken Seite, daher müssen auf der linken Seite alle Fälle abgedeckt werden. Beim absurd pattern werden explizite oder implizite Argumente, aufgrund derer kein Ausdruck auf der rechten Seite gefunden werden kann, durch 9 ein rundes resp. geschwungenes, leeres Klammerpaar ((), {}) ersetzt [14, S. 9 f.]. Diese Argumente dürfen nicht konstruierbar sein. Ein Beispiel hierfür findet sich in Listing 8. Das absurd pattern wird in der Funktion halbieren verwendet, die als Argument einen Rückgabewert der Funktion gerade entgegennimmt. Ist eine Zahl n nicht gerade, so gibt letztere Funktion den nichtkonstruierbaren Typ Unwahrheit zurück. In genau diesem Fall ist im absurd pattern keine rechte Seite gegeben. data N : Set where null : N nachf : N → N data Unwahrheit : Set where data Wahrheit : Set where wahr : Wahrheit gerade gerade gerade gerade : N → Set null ( nachf null ) ( nachf ( nachf n ) ) halbieren halbieren halbieren halbieren : (n : null p ( nachf ( nachf = wahr = Unwahrheit = gerade n N) → gerade n → N = null null ) () ( nachf n ) ) p = nachf ( halbieren n p ) Listing 8: Mit dem absurd pattern werden Fälle im pattern matching behandelt bei denen keine rechte Seite gegeben werden kann. 5 Abschließende Betrachtung Agda wird vorrangig als Beweisassistent verwendet. Lemmata werden dabei als Typen in der Sprache Agda formuliert und ihre Korrektheit wird durch ihre Konstruierbarkeit gezeigt. Dies ergibt sich daraus, dass das Typsystem die Typentheorie von Martin-Löf umsetzt. Die Syntax von Agda erinnert an jene von Haskell, hieraus ergibt sich eine gute Lesbarkeit von in Agda formuliertem Code für Aussenstehende. Im Gegensatz zu anderen Beweisassistenten wie Isabelle oder Coq können in Agda keine Taktiken zur Formulierung von Beweisen eingesetzt werden, d.h. Beweise können in Agda ausschließlich nichtautomatisiert geführt werden. Eine interaktive Beweisführung ist insofern nur mittels der vorhergehend beschriebenen holes möglich. Ein grundsätzlicher Vorteil gegenüber anderen Beweisassistenten besteht in der Ausführbarkeit von in Agda geschriebenem Code, dabei ist die Implementierung von Ein- und Ausgabe allerdings ähnlich umständlich wie bei Haskell, zudem existieren in Agda keine imperativen Konzepte wie etwa die do-Notation. Tatsächlich wird Agda daher als Beweisassistent eingesetzt, steht in dieser Funktion jedoch hinter reinen Beweisassistenten wie etwa Coq zurück. Literatur [1] Andreas Abel. An introduction to dependent types and Agda. 2009. 10 [2] Richard Baldus. Formalismus und Intuitionismus in der Mathematik. G. Braun, Karlsruhe, 1924. [3] Ana Bove, Peter Dybjer, and Ulf Norell. A brief overview of Agda–a functional language with dependent types. In Theorem Proving in Higher Order Logics, pages 73–78. Springer, 2009. [4] TH Chalmers. The Agda Wiki. http://wiki.portal.chalmers.se/agda/, 2015. [Zugriff 1. April 2015]. [5] Catarina Coquand and Thierry Coquand. Structured type theory. In Workshop on Logical Frameworks and Metalanguages, 1999. [6] Henry DeYoung and Stephanie Balzer. 15-819 Homotopy type theory lecture notes. 2013. http://www.cs.cmu.edu/ rwh/courses/hott/notes/notes week1.pdf. [7] Allen Hatcher. Algebraic topology. Cambridge University Press, 2002. [8] homotopytypetheory.org. Development of homotopy type theory in Agda. https://github.com/HoTT/HoTT-Agda, 2013. [Zugriff 1. April 2015]. [9] Robert Lewis and Joseph Tassarotti. 15-819 Homotopy type theory lecture notes. 2013. http://www.cs.cmu.edu/ rwh/courses/hott/notes/notes week6.pdf. [10] Per Martin-Löf. Intuitionistic type theory. Naples: Bibliopolis, 1984. Abrufbar unter http://people.csail.mit.edu/jgross/personal-website/papers/academic-paperslocal/Martin-Lof80.pdf. [11] Conor Thomas McBride. How to keep your neighbours in order. In Proceedings of the 19th ACM SIGPLAN international conference on Functional programming, pages 297–309. ACM, 2014. [12] Bengt Nordström, Kent Petersson, and Jan M Smith. Programming in Martin-Löfs type theory, volume 200. Oxford University Press Oxford, 1990. [13] Ulf Norell. Towards a practical programming language based on dependent type theory, volume 32. Citeseer, 2007. [14] Ulf Norell. Dependently typed programming in Agda. In Advanced Functional Programming, pages 230–266. Springer, 2009. [15] Li Nuo. Representing numbers in Agda. Technical report, 2010. [16] Simon Thompson. Type theory and functional programming. Addison Wesley, 1991. [17] Silvio Valentini. Another introduction to Martin-Löf ’s Intuitionistic Type Theory. Universit di Padova, 1996. [18] Vladimir Voevodsky et al. Homotopy type theory: Univalent foundations of mathematics. Institute for Advanced Study (Princeton), The Univalent Foundations Program, 2013. 11