Seminar: Fortgeschrittene Konzepte der funktionalen

Werbung
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
Herunterladen