marp | title | author | theme | paginate | math | style |
---|---|---|---|---|---|---|
true |
Generalized Algebraic Data Types in OCaml |
Marius Weidner |
uncover |
true |
katex |
:root {
font-family: 'JetBrains Mono', serif !important;
font-variant-ligatures: common-ligatures;
}
code {
font-family: 'JetBrains Mono', serif !important;
font-variant-ligatures: common-ligatures;
border-radius: 12px;
}
pre {
font-size: 1rem;
border-radius: 12px;
}
p {
font-family: 'JetBrains Mono', serif !important;
font-variant-ligatures: common-ligatures;
}
section::after {
background: none
}
.columns {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.75rem;
}
.subtitle {
font-size: 0.7rem;
letter-spacing: 0.00000001rem;
}
footer {
color: black;
}
|
$$ \begin{align*}
Expr ::=& \text{ } \text{ true} \text{ } \&| \text{ } \text{false} \text{ } \&| \text{ } -^?0..9^+ \&| \textbf{ if } Expr \textbf{ then } Expr \textbf{ else } Expr \end{align*} $$
<style scoped> pre { font-size: 0.8rem; } div.error > pre { font-size: 0.777rem; border: 0.05rem; background-color: rgb(242, 241, 244); border-color: #B00020; border-style: solid; border-radius: 12px; } </style>
Gültige Programme
true
if true then 42 else 0
if true then
if true then 42 else 0
else
0
Ungültige Programme
if true then 0
if 0 then true else false
if true then
if true then 42 else 0
else
false
<style scoped> pre { font-size: 1rem; } </style>
type expr =
| Bool of bool
| Int of int
| If of expr * expr * expr
Syntaxbaum ohne GADTs
let rec eval : expr -> expr = function
| If (c, t, e) -> begin match eval c with
| Bool true -> eval t
| Bool false -> eval e
| _ -> failwith "need bool!"
end
| e -> e
Evaluationsfunktion ohne GADTs
<style scoped> pre { font-size: 0.7rem; } </style>
eval (If
(Bool true,
(Int 42),
(Int 0)))
- : expr = Int 42
eval (If
(Int 42,
(Bool false),
(Int 0)))
Exception: Failure "need bool!"
Beispiele ohne GADTs
- Ungültige Programmdefinitionen
- Laufzeitfehler im Interpreter
- Zweige mit verschiedenen Typen
<style scoped> pre { font-size: 0.9rem; } </style>
type _ expr =
| Bool : bool -> bool expr
| Int : int -> int expr
| If : bool expr * 'a expr * 'a expr -> 'a expr
Syntaxbaum mit GADTs
<style scoped> pre { font-size: 0.85rem; } </style>
let rec eval : .. = function
| Bool b -> b
| Int i -> i
| If (c, t, e) -> if eval c then eval t else eval e
Evaluationsfunktion mit GADTs
<style scoped> pre { font-size: 0.8rem; } div.error > pre { font-size: 0.77rem; border: 0.1rem; background-color: rgb(242, 241, 244); border-color: #B00020; border-style: solid; border-radius: 12px; } </style>
eval (If
(Int 42,
(Bool true),
(Bool false)))
eval (If
(Bool true,
(Bool false),
(Int 42)))
Error: Type int is not compatible with type bool
Beispiele mit GADTs
- Nur gültige Programmdefinitionen
- Keine Laufzeitfehler im Interpreter
- Exhaustive Patternmatching
<style scoped> pre { font-size: 0.85rem; border: 0.1rem; border-color: #B00020; border-style: solid; border-radius: 12px; } </style>
let rec eval (type a) (e : a expr) : a = match e with
| Bool b -> b
| Int i -> i
| If (c, t, e) -> if eval c then eval t else eval e
Error: This expression has type a expr but an
expression was expected of type bool expr
Evaluationsfunktion mit GADTs
<style scoped> pre { font-size: 0.75rem; } </style>
let rec eval : 'a. 'a expr -> 'a =
fun (type a) (e : a expr) : a -> match e with
| Bool b -> b
| Int i -> i
| If (c, t, e) -> if eval c then eval t else eval e
Evaluationsfunktion mit GADTs
<style scoped> pre { font-size: 0.8rem; } </style>
let rec eval : type a. a expr -> a = function
| Bool b -> b
| Int i -> i
| If (c, t, e) -> if eval c then eval t else eval e
Evaluationsfunktion mit GADTs
type stringable =
Stringable : {
item: 'a;
to_string: 'a -> string
} -> stringable
let print (Stringable s) =
print_endline (s.to_string s.item)
<style scoped> pre { font-size: 0.75rem; } </style>
type (_, _) mode =
| Unsafe : ('a, 'a) mode
| Option : ('a, 'a option) mode
let first : type a r. a list -> (a, r) mode -> r =
fun lst mde -> match lst with
| hd :: tl -> (match mde with
| Unsafe -> hd
| Option -> Some hd)
| [ ] -> (match mde with
| Unsafe -> failwith "list is empty"
| Option -> None)
-
Typinferenz unentscheidbar
$\rightarrow$ Typannotationen notwendig -
|
-Patterns nicht auflösbar$\rightarrow$ Manuell auflösen und Logik auslagern -
[@@-deriving ..]
-Annotation nicht möglich$\rightarrow$ Non-GADT Version benötigt
- GADTs erlauben Konstrukturen verschiedene Typparameter einzusetzen
- Stärkere Aussagen auf Typebene möglich
- Patternmatching nutzt die zusätzlichen Informationen
- GATDs erlauben existenziell quantifizierte Typen zu formen
- Typinferenz wird unentscheidbar
- Real World OCaml: GADTs
Yaron Minsky, Anil Madhavapeddy2021
- Detecting use-cases for GADTs in OCaml Mads Hartmann
2015
- Stanford CS242: Programming Languages
Will Crichton
2019