Kurz: Ein Variantentyp beschreibt „entweder A oder B oder C“, oft mit Daten pro Fall. Der Compiler prüft, dass match alle Fälle behandelt:
Teil des Kurses OCaml
Variantentypen
Ein Variantentyp beschreibt „entweder A oder B oder C“, oft mit Daten pro Fall. Der Compiler prüft, dass match alle Fälle behandelt:
type farbe = Rot | Gruen | Blau
type form =
| Kreis of float
| Rechteck of float * float
| Dreieck of float * float * float
let farbname = function
| Rot -> "rot"
| Gruen -> "grün"
| Blau -> "blau"
let flaeche = function
| Kreis r -> 3.14159 *. r *. r
| Rechteck (b, h) -> b *. h
| Dreieck (a, b, c) ->
let s = (a +. b +. c) /. 2.0 in
sqrt (s *. (s -. a) *. (s -. b) *. (s -. c))
let () =
print_endline (farbname Gruen);
List.iter (fun f -> Printf.printf "%.2f\n" (flaeche f))
[Kreis 1.0; Rechteck (2.0, 3.0); Dreieck (3.0, 4.0, 5.0)]Ausgabe:
grün
3.14
6.00
6.00Rekursive Typen: Ausdrücke und Bäume
type ausdruck =
| Zahl of int
| Plus of ausdruck * ausdruck
| Mal of ausdruck * ausdruck
| Neg of ausdruck
let rec eval = function
| Zahl n -> n
| Plus (a, b) -> eval a + eval b
| Mal (a, b) -> eval a * eval b
| Neg a -> - (eval a)
let rec zeige = function
| Zahl n -> string_of_int n
| Plus (a, b) -> "(" ^ zeige a ^ " + " ^ zeige b ^ ")"
| Mal (a, b) -> zeige a ^ " * " ^ zeige b
| Neg a -> "-" ^ zeige a
type 'a baum = Blatt | Knoten of 'a baum * 'a * 'a baum
let rec einfuegen x = function
| Blatt -> Knoten (Blatt, x, Blatt)
| Knoten (l, w, r) as k ->
if x < w then Knoten (einfuegen x l, w, r)
else if x > w then Knoten (l, w, einfuegen x r)
else k
let rec in_reihenfolge = function
| Blatt -> []
| Knoten (l, w, r) -> in_reihenfolge l @ [w] @ in_reihenfolge r
let rec hoehe = function
| Blatt -> 0
| Knoten (l, _, r) -> 1 + max (hoehe l) (hoehe r)
let () =
let e = Mal (Plus (Zahl 1, Zahl 2), Neg (Zahl 4)) in
Printf.printf "%s = %d\n" (zeige e) (eval e);
let b = List.fold_left (fun acc x -> einfuegen x acc) Blatt [5; 3; 8; 1; 4; 7; 9; 3] in
List.iter (Printf.printf "%d ") (in_reihenfolge b);
print_newline ();
Printf.printf "Höhe %d\n" (hoehe b)Ausgabe:
(1 + 2) * -4 = -12
1 3 4 5 7 8 9
Höhe 3'a baum ist ein polymorpher Typ: Der Baum funktioniert für jeden Elementtyp.
Result: Fehler als Werte
type fehler = Division_durch_null | Negativ of int
let teile a b = if b = 0 then Error Division_durch_null else Ok (a / b)
let wurzel n = if n < 0 then Error (Negativ n) else Ok (int_of_float (sqrt (float_of_int n)))
let berechne a b =
Result.bind (teile a b) (fun q -> wurzel q)
let melde = function
| Ok v -> Printf.printf "Ok %d\n" v
| Error Division_durch_null -> print_endline "Fehler: durch null"
| Error (Negativ n) -> Printf.printf "Fehler: %d negativ\n" n
let () =
melde (berechne 100 4);
melde (berechne 1 0);
melde (berechne (-16) 2)Ausgabe:
Ok 5
Fehler: durch null
Fehler: -8 negativAusnahmen
Für unerwartete Fehler gibt es Exceptions:
exception Eigener_fehler of string
let pruefe n = if n < 0 then raise (Eigener_fehler "negativ") else n
let () =
(try ignore (pruefe (-1)) with Eigener_fehler m -> print_endline ("gefangen: " ^ m));
(try ignore (10 / 0) with Division_by_zero -> print_endline "durch null");
(try ignore (List.hd []) with Failure m -> print_endline ("Failure: " ^ m));
(try ignore (int_of_string "abc") with Failure m -> print_endline m);
(try ignore (Hashtbl.find (Hashtbl.create 1) "x") with Not_found -> print_endline "nicht gefunden")Ausgabe:
gefangen: negativ
durch null
Failure: hd
int_of_string
nicht gefundenMerke
type t = A | B of intdefiniert Varianten;matchwird vollständig geprüft- Rekursive und polymorphe (
'a) Typen modellieren Ausdrücke und Bäume result(Ok/Error) für erwartbare Fehler,exceptionfür Ausnahmenas,whenund verschachtelte Muster machenmatchmächtig
Übungsaufgabe
Erweitere ausdruck um Division und gib bei Division durch null ein Error zurück.
Quiz zur Selbstkontrolle
Was prüft der OCaml-Compiler bei match?
- Ob alle Fälle abgedeckt sind (Warnung bei Lücken) (richtig)
- Ob die Reihenfolge alphabetisch ist
- Nichts
- Nur Zahlen
Was bedeutet 'a in 'a baum?
- Einen beliebigen Typparameter (Polymorphie) (richtig)
- Ein Zeichen
- Ein Attribut
- Ein Alias
Wofür dient result?
- Ok oder Error als Rückgabewert statt Exception (richtig)
- Für Schleifen
- Für Typen
- Für Module
Weiter im Kurs
Zurück: Listen, Tupel und Records
Weiter: Module, Strings und Standardbibliothek
Alle Kapitel: OCaml im Überblick