Created
December 20, 2020 11:56
-
-
Save ebresafegaga/00f84e41f8731e09f6789d86ca73db8e to your computer and use it in GitHub Desktop.
Encoding existential types in OCaml with universal types
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* A stack with an existential/abstract type 't *) | |
type 'a stack = | |
Stack: { to_list: 't -> 'a list; | |
of_list: 'a list -> 't; | |
empty: 't; | |
push: 'a -> 't -> 't; | |
pop: 't -> ('t * 'a) option } -> | |
'a stack | |
let stackInstance = | |
Stack { to_list = Fun.id; | |
of_list = Fun.id; | |
empty = []; | |
push = (fun x xs -> x :: xs); | |
pop = function [] -> None | x :: xs -> Some (xs, x) } | |
let test () = | |
let Stack {of_list; to_list; empty; push; pop} = stackInstance in | |
let e = empty |> push 29 |> push 34 |> push 78 in | |
let v = | |
match pop e with | |
| None -> 0 | |
| Some (_, x) -> x | |
in | |
to_list e | |
(* OCaml has polymorphic records, which can be used to emulate higher-rank polymorphism (RankNTypes) *) | |
(* We will now use it to encode existential types *) | |
(* 't is the abstract type, 'b is the element of the stack, | |
'a is the result of computation that uses the stack *) | |
type 'b uniStack = { ff: 'a. ('a, 'b) inner -> 'a } | |
and ('a, 'b) inner = {f: 't. to_list:('t -> 'b list) -> | |
of_list:('b list -> 't) -> | |
empty:'t -> | |
push:('b -> 't -> 't) -> | |
pop:('t -> ('t * 'b) option) -> 'a } | |
let uniStackInstance = | |
{ ff = fun {f} -> f ~to_list:Fun.id ~of_list:Fun.id | |
~empty:[] | |
~push:(fun x xs -> x :: xs) | |
~pop:(function [] -> None | x :: xs -> Some (xs, x)) } | |
let test () = | |
let {ff} = uniStackInstance in | |
ff { f = fun ~to_list ~of_list ~empty ~push ~pop -> | |
let n = empty |> push 45 in | |
let b = of_list [2;4;4] in | |
let c = to_list b in | |
pop b | |
|> Fun.flip Option.bind (fun (_, v) -> Some (v + 1)) | |
|> Option.value ~default:56 } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment