Vorsicht bei redundanten und unvollständigen Matches!

Ähnliche Dokumente
2.5 Listen. Kurzschreibweise: [42; 0; 16] Listen werden mithilfe von [] und :: konstruiert.

Anwendung (2. Versuch:-) Entkopplung der Locks

Die Definition eines Typen kann rekursiv sein, d.h. Typ-Konstruktoren dürfen Elemente des zu definierenden Typ erhalten.

Verarbeitung unendlicher Datenstrukturen Jetzt können wir z.b. die unendliche Liste aller geraden Zahlen oder aller Quadratzahlen berechnen:

Informatik 2. Wintersemester 2017/18. Helmut Seidl. Institut für Informatik TU München

Informatik 2. Wintersemester 2016/17. Helmut Seidl. Institut für Informatik TU München

ALP I. Funktionale Programmierung

Teil XII. Funktionale Programmiersprachen

Helmut Seidl. Informatik 2. TU München

Beispiele: Funktionsabstraktion (3) Funktionsdeklaration. Funktionsdeklaration (2) Funktionsdeklaration (3) 3. Abstraktion über Funktionsbezeichner:

Objektorientierte Programmierung. Kapitel 22: Aufzählungstypen (Enumeration Types)

Crashkurs Haskell Mentoring WiSe 2016/17. Anja Wolffgramm Freie Universität Berlin

Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny

Grundlagen der Programmierung 2

Aufgabe 1 Basiswissen zur Vorlesung (8 Punkte)

Funktionale Programmierung

Grundlegende Datentypen

Programmierkurs II. Typsynonyme & algebraische Datentypen

Grundlegende Datentypen

Induktion nach der Länge n von x

Kapitel 3. Funktionale Programmierung in OCAML. Informatik I WS03/04 Martin Hofmann 90

Einführung in die funktionale Programmierung

Grundlegende Datentypen

Gliederung. Algorithmen und Datenstrukturen I. Listen in Haskell: Listen in Haskell: Listen in Haskell. Datentyp Liste Strings Listenkomprehension

Listen und Listenfunktionen. Grundlagen der Programmierung 2 A (Listen) Listen und Listenfunktionen. Listen? Haskell: Listen

Funktionale Programmierung Grundlegende Datentypen

Software Entwicklung 1. Fallstudie: Arithmetische Ausdrücke. Rekursive Klassen. Überblick. Annette Bieniusa / Arnd Poetzsch-Heffter

Software Entwicklung 1

Lösungshinweise/-vorschläge zur Altklausur Abschlussklausur 06/07

Haskell. Grundlagen der Programmierung 2. Grundlagen der Programmierung 2 (1.A) Bücher, Literatur, URLs. Haskell. Einführung

Kapitel 2. Mathematische Grundlagen. Skript zur Vorlesung Einführung in die Programmierung

Paradigmen der Programmierung

TECHNISCHE UNIVERSITÄT MÜNCHEN FAKULTÄT FÜR INFORMATIK

Lösungshinweise/-vorschläge zum Übungsblatt 4: Grundlagen der Programmierung (WS 2018/19)

Grundlagen der Programmierung 2 (2.A)

1. Probeklausur (Lösung) zu Programmierung 1 (WS 07/08)

Programmierung WS 2002 / 03: Musterlösung zum 12. Übungsblatt

Grundprinzipien der funktionalen Programmierung

Programmierung und Modellierung

C++ Teil 5. Sven Groß. 12. Nov IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 16

Grundlagen der Programmierung 2

Abschnitt 3: Mathematische Grundlagen

Die Korrektheit von Mergesort

Programmierparadigmen

Was bisher geschah. deklarative Programmierung. funktionale Programmierung (Haskell):

Grundlagen der Programmierung 2 A (Listen)

Grundlagen der Programmierung 2. Operationale Semantik

Programmierung 1 (Wintersemester 2012/13) Lösungsblatt 4 (Kapitel 4)

Grundlagen der Programmierung 2 (1.A)

Allgemeine Hinweise: TECHNISCHE UNIVERSITÄT MÜNCHEN. Name Vorname Studiengang Matrikelnummer. Hörsaal Reihe Sitzplatz Unterschrift

Haskell. Grundlagen der Programmierung 2. Grundlagen der Programmierung 2: Geplanter Inhalt der ersten Hälfte. Prof. Dr. Manfred Schmidt-Schauß

Java Übung. Übung 2. Werner Gaulke. 19. April Universität Duisburg-Essen Kommedia, Übung EinPro SS06, Einführung in Java - Übung.

Funktionale Programmierung. ALP I Lambda-Kalkül. Teil III SS Prof. Dr. Margarita Esponda. Prof. Dr. Margarita Esponda

Abschnitt 3: Mathematische Grundlagen

Tag 7. Pattern Matching und eigene Datentypen

Methoden. Gerd Bohlender. Einstieg in die Informatik mit Java, Vorlesung vom

DieÜbersetzung funktionaler Programmiersprachen

FAKULTÄT FÜR INFORMATIK

Vorsemesterkurs Informatik Sommersemester Aufgabenblatt Nr. 5A. Lösung zu Aufgabe 1 (Fehler in Haskell-Quelltext: Parsefehler)

Grundlagen der Programmierung in C Funktionen

XML-Dokumente (Tabmente) in OCAML

Grundlagen der Programmierung 2 (1.A)

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Einige andere Programmiersprachen. Typisierung in Haskell

WS 2011/2012. RobertGiegerich. November 12, 2013

WS 2011/2012. RobertGiegerich. November 12, 2013

Konzepte von Programmiersprachen

Crashkurs: Haskell. Mentoring FU Berlin Felix Droop

12 Abstrakte Klassen, finale Klassen und Interfaces

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme

Aufgabe 1.1. Wählen Sie jene Variablendeklarationen mit Initialisierungen aus, die in Java hinsichtlich der Typen korrekt sind:

Software Entwicklung 1. Rekursion. Beispiel: Fibonacci-Folge I. Motivation. Annette Bieniusa / Arnd Poetzsch-Heffter

Programmieren in Haskell

C++ Teil 5. Sven Groß. 16. Nov Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 16

Grundelemente objektorientierter Sprachen (1)

Implementieren von Klassen

Lösungen zum Übungsblatt 3: Softwareentwicklung I (WS 2006/07)

Grundlagen der Programmierung 3 A

Funktionale Programmierung Mehr funktionale Muster

Tutoraufgabe 1 (Implementierung eines ADTs):

3.1 Reservierte Wörter

SWP Funktionale Programme (2. Teil)

INFORMATIK FÜR BIOLOGEN

Inhalt Kapitel 5: Funktionen höherer Ordnung

Grundlagen der Programmierung 3 A

HASKELL KAPITEL 2.1. Notationen: Currying und das Lambda-Kalkül

II.3.1 Rekursive Algorithmen - 1 -

1.1 Abstrakte Datentypen 1.2 Lineare Strukturen 1.3 Bäume 1.4 Prioritätsschlangen 1.5 Graphen

C++ Teil 2. Sven Groß. 16. Apr IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Apr / 22

Funktionale Programmierung ALP I. Funktionen höherer Ordnung SS Prof. Dr. Margarita Esponda. Prof. Dr. Margarita Esponda

Programmieren in Java

D-BAUG Informatik I. Exercise session: week 1 HS 2018

Die Schnittstelle Comparable

Transkript:

Vorsicht bei redundanten und unvollständigen Matches! # let n = 7;; val n : int = 7 # match n with 0 -> "null";; Warning: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: 1 Exception: Match_failure ("", 5, -13). # match n with 0 -> "null" 0 -> "eins" _ -> "Soweit kann ich nicht zaehlen!";; Warning: this match case is unused. - : string = "Soweit kann ich nicht zaehlen!" 149

2.5 Listen Listen werden mithilfe von [] und :: konstruiert. Kurzschreibweise: [42; 0; 16] # let mt = [];; val mt : a list = [] # let l1 = 1::mt;; val l1 : int list = [1] # let l = [1;2;3];; val l : int list = [1; 2; 3] # let l = 1::2::3::[];; val l : int list = [1; 2; 3] 150

Achtung: Alle Elemente müssen den gleichen Typ haben: # 1.0::1::[];; This expression has type int but is here used with type float tau list beschreibt Listen mit Elementen vom Typ tau :-) Der Typ a ist eine Typ-Variable: [] bezeichnet eine leere Liste für beliebige Element-Typen :-)) 151

Achtung: Alle Elemente müssen den gleichen Typ haben: # 1.0::1::[];; This expression has type int but is here used with type float tau list beschreibt Listen mit Elementen vom Typ tau :-) Der Typ a ist eine Typ-Variable: [] bezeichnet eine leere Liste für beliebige Element-Typen :-)) 152

Pattern Matching auf Listen: # match l with [] -> -1 x::xs -> x;; -: int = 1 153

2.6 Definitionen von Funktionen # let double x = 2*x;; val double : int -> int = <fun> # (double 3, double (double 1));; - : int * int = (6,4) Nach dem Funktionens-Namen kommen die Parameter. Der Funktionsname ist damit auch nur eine Variable, deren Wert eine Funktion ist :-) 154

Alternativ können wir eine Variable einführen, deren Wert direkt eine Funktion beschreibt... # let double = fun x -> 2*x;; val double : int -> int = <fun> Diese Funktionsdefinition beginnt mit fun, gefolgt von den formalen Parametern. Nach -> kommt die Berechnungsvorschrift. Die linken Variablen dürfen rechts benutzt werden :-) 155

Achtung: Funktionen sehen die Werte der Variablen, die zu ihrem Definitionszeitpunkt sichtbar sind: # let faktor = 2;; val faktor : int = 2 # let double x = faktor*x;; val double : int -> int = <fun> # let faktor = 4;; val faktor : int = 4 # double 3;; - : int = 6 156

Achtung: Eine Funktion ist ein Wert: # double;; - : int -> int = <fun> 157

Rekursive Funktionen: Eine Funktion ist rekursiv, wenn sie sich selbst aufruft. # let rec fac n = if n<2 then 1 else n * fac (n-1);; val fac : int -> int = <fun> # let rec fib = fun x -> if x <= 1 then 1 else fib (x-1) + fib (x-2);; val fib : int -> int = <fun> Dazu stellt Ocaml das Schlüsselwort rec bereit :-) 158

Rufen mehrere Funktionen sich gegenseitig auf, heißen sie verschränkt rekursiv. # let rec even n = if n=0 then "even" else odd (n-1) and odd n = if n=0 then "odd" else even (n-1);; val even : int -> string = <fun> val odd : int -> string = <fun> Wir kombinieren ihre Definitionen mit dem Schlüsselwort and :-) 159

Definition durch Fall-Unterscheidung: # let rec len = fun l -> match l with [] -> 0 x::xs -> 1 + len xs;; val len : a list -> int = <fun> # len [1;2;3];; - : int = 3... kann kürzer geschrieben werden als: # let rec len = function [] -> 0 x::xs -> 1 + len xs;; val len : a list -> int = <fun> # len [1;2;3];; - : int = 3 160

Definition durch Fall-Unterscheidung: # let rec len = fun l -> match l with [] -> 0 x::xs -> 1 + len xs;; val len : a list -> int = <fun> # len [1;2;3];; - : int = 3... kann kürzer geschrieben werden als: # let rec len = function [] -> 0 x::xs -> 1 + len xs;; val len : a list -> int = <fun> # len [1;2;3];; - : int = 3 161

Fall-Unterscheidung bei mehreren Argumenten: # let rec app l y = match l with [] -> y x::xs -> x :: app xs y;; val app : a list -> a list -> a list = <fun> # app [1;2] [3;4];; - : int list = [1; 2; 3; 4]... kann auch geschrieben werden als: # let rec app = function [] -> fun y -> y x::xs -> fun y -> x::app xs y;; val app : a list -> a list -> a list = <fun> # app [1;2] [3;4];; - : int list = [1; 2; 3; 4] 162

Fall-Unterscheidung bei mehreren Argumenten: # let rec app l y = match l with [] -> y x::xs -> x :: app xs y;; val app : a list -> a list -> a list = <fun> # app [1;2] [3;4];; - : int list = [1; 2; 3; 4]... kann auch geschrieben werden als: # let rec app = function [] -> fun y -> y x::xs -> fun y -> x::app xs y;; val app : a list -> a list -> a list = <fun> # app [1;2] [3;4];; - : int list = [1; 2; 3; 4] 163

Lokale Definitionen Definitionen können mit let lokal eingeführt werden: # let x = 5 in let sq = x*x in sq+sq;; - : int = 50 # let facit n = let rec iter m yet = if m>n then yet else iter (m+1) (m*yet) in iter 2 1;; val facit : int -> int = <fun> 164

2.7 Benutzerdefinierte Typen Beispiel: Spielkarten Wie kann man die Farbe und den Wert einer Karte spezifizieren? 1. Idee: Benutze Paare von Strings und Zahlen, z.b. ("Karo",10) ("Kreuz",12) ("Pik",1) Karo Zehn Kreuz Bube Pik As 165

Nachteile: Beim Test auf eine Farbe muss immer ein String-Vergleich stattfinden ineffizient! Darstellung des Buben als 12 ist nicht intuitiv unleserliches Programm! Welche Karte repräsentiert das Paar ("Kaor",1)? (Tippfehler werden vom Compiler nicht bemerkt) Besser: Aufzählungstypen von Ocaml. 166

Beispiel: Spielkarten 2. Idee: Aufzählungstypen # type farbe = Karo Herz Pik Kreuz;; type farbe = Karo Herz Pik Kreuz # type wert = Neun Bube Dame Koenig Zehn As;; type wert = Neun Bube Dame Koenig Zehn As # Kreuz;; - : farbe = Kreuz # let pik_bube = (Pik,Bube);; val pik_bube : farbe * wert = (Pik, Bube) 167

Vorteile: Darstellung ist intuitiv. Tippfehler werden erkannt: # (Kaor,As);; Unbound constructor Kaor Die interne Repräsentation ist effizient :-) Bemerkungen: Durch type wird ein neuer Typ definiert. Die Alternativen heißen Konstruktoren und werden durch getrennt. Jeder Konstruktor wird groß geschrieben und ist eindeutig einem Typ zugeordnet. 168

Aufzählungstypen (cont.) Konstruktoren können verglichen werden: # Kreuz < Karo;; - : bool = false;; # Kreuz > Karo;; - : bool = true;; Pattern Matching auf Konstruktoren: # let isttrumpf = function (Karo,_) -> true (_,Bube) -> true (_,Dame) -> true (Herz,Zehn) -> true (_,_) -> false;; 169

val isttrumpf : farbe * wert -> bool = <fun> Damit ergibt sich z.b.: # isttrumpf (Karo,As);; - : bool = true # isttrumpf (Pik,Koenig);; - : bool = false Eine andere nützliche Funktion: 170

# let string_of_farbe = function Karo -> "Karo" Herz -> "Herz" Pik -> "Pik" Kreuz -> "Kreuz";; val string_of_farbe : farbe -> string = <fun> Beachte: Die Funktion string_of_farbe wählt für eine Farbe in konstanter Zeit den zugehörigen String aus(der Compiler benutzt hoffentlich Sprungtabellen :-) 171

Jetzt kann Ocaml schon fast Karten spielen: # let sticht = function ((Herz,Zehn),_) -> true (_,(Herz,Zehn)) -> false ((f1,dame),(f2,dame)) -> f1 > f2 ((_,Dame),_) -> true (_,(_,Dame)) -> false ((f1,bube),(f2,bube)) -> f1 > f2 ((_,Bube),_) -> true (_,(_,Bube)) -> false ((Karo,w1),(Karo,w2)) -> w1 > w2 ((Karo,_),_) -> true (_,(Karo,_)) -> false ((f1,w1),(f2,w2)) -> if f1=f2 then w1 > w2 else false;; 172

... # let nimm (karte2,karte1) = if sticht (karte2,karte1) then karte2 else karte1;; # let stich (karte1,karte2,karte3,karte4) = nimm (karte4, nimm (karte3, nimm (karte2,karte1)));; # stich ((Herz,Koenig),(Karo,As), (Herz,Bube),(Herz,As));; - : farbe * wert = (Herz, Bube) # stich((herz,koenig),(pik,as), (Herz,Koenig),(Herz,As));; - : farbe * wert = (Herz, As) 173