Skip to content

Commit d53737d

Browse files
committed
Implement simple demonstration of encoding existential types in terms of polymorphism
1 parent 10117ca commit d53737d

File tree

4 files changed

+122
-1
lines changed

4 files changed

+122
-1
lines changed

example/example.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module Boolean = Boolean
22
module ExampleHelpers = ExampleHelpers
3+
module Existential = Existential
34
module Mixed = Mixed
45
module ModularArithmetic = ModularArithmetic
56
module Polymorphism = Polymorphism

example/existential.ml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
open Metatypes
2+
open TypeOperations.MapType
3+
open ExampleHelpers
4+
open Recursive
5+
6+
(* TODO: create some helper functions to make existential encoding easier to use *)
7+
8+
let new_label = typed_term (Const "new")
9+
let get_label = typed_term (Const "get")
10+
let inc_label = typed_term (Const "inc")
11+
12+
(* Represents the type `CounterModule = {new: Counter, get: Counter -> Nat, inc: Counter -> Counter}` *)
13+
let counter_module =
14+
map_type
15+
(fun int ->
16+
[
17+
Intersection
18+
[
19+
(new_label.rtype.union, [ UnivTypeVar 0 ]);
20+
( get_label.rtype.union,
21+
[ Intersection [ ([ UnivTypeVar 0 ], int) ] ] );
22+
( inc_label.rtype.union,
23+
[ Intersection [ ([ UnivTypeVar 0 ], [ UnivTypeVar 0 ]) ] ] );
24+
];
25+
])
26+
ind_integer
27+
28+
(* Represents `forall Counter. (CounterModule -> Y)`, the "continuation" at the
29+
core of the polymorphic encoding of existential types *)
30+
let counter_continuation =
31+
map_type
32+
(fun counter_module_union ->
33+
[
34+
UnivQuantification
35+
[ Intersection [ (counter_module_union, [ UnivTypeVar 1 ]) ] ];
36+
])
37+
counter_module
38+
39+
(*
40+
Represents the existential package type:
41+
`{exists Counter, CounterModule}`
42+
encoded using polymoprhism as:
43+
`forall Y.((forall Counter.(CounterModule -> Y) -> Y)`
44+
*)
45+
let counter_package_type =
46+
map_type
47+
(fun counter_continuation_union ->
48+
[
49+
UnivQuantification
50+
[ Intersection [ (counter_continuation_union, [ UnivTypeVar 0 ]) ] ];
51+
])
52+
counter_continuation
53+
54+
(* Term representing a counter ADT, encoded using polymoprhism, using Int as the implementation for Counter *)
55+
let counter_adt =
56+
typed_term
57+
(UnivQuantifier
58+
(Abstraction
59+
[
60+
( counter_continuation,
61+
Application
62+
( UnivApplication (Variable 0, ind_integer),
63+
Abstraction
64+
[
65+
(new_label.rtype, one.term);
66+
( get_label.rtype,
67+
Abstraction [ (ind_integer, Variable 0) ] );
68+
( inc_label.rtype,
69+
Abstraction
70+
[
71+
( ind_integer,
72+
Application (increment.term, Variable 0) );
73+
] );
74+
] ) );
75+
]))

test/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(tests
2-
(names base boolean mixed modularArithmetic polymorphism recursive unions)
2+
(names base boolean existential mixed modularArithmetic polymorphism recursive unions)
33
(libraries setTypedLambda setTypedLambdaExample))
44

55
(env

test/existential.ml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
open SetTypedLambdaExample.Existential
2+
open SetTypedLambdaExample.Recursive
3+
open SetTypedLambdaExample.ExampleHelpers
4+
open TypeOperations.Subtype
5+
open TestHelpers
6+
7+
let get_new_counter =
8+
typed_term
9+
(Application
10+
( UnivApplication (counter_adt.term, ind_integer),
11+
UnivQuantifier
12+
(Abstraction
13+
[
14+
( counter_module,
15+
Application
16+
( Application (Variable 0, get_label.term),
17+
Application (Variable 0, new_label.term) ) );
18+
]) ))
19+
20+
let get_incremented_counter =
21+
typed_term
22+
(Application
23+
( UnivApplication (counter_adt.term, ind_integer),
24+
UnivQuantifier
25+
(Abstraction
26+
[
27+
( counter_module,
28+
Application
29+
( Application (Variable 0, get_label.term),
30+
Application
31+
( Application (Variable 0, inc_label.term),
32+
Application (Variable 0, new_label.term) ) ) );
33+
]) ))
34+
35+
let () =
36+
test "Counter ADT has expected type"
37+
(is_subtype counter_adt.rtype counter_package_type)
38+
39+
let () =
40+
test "Get new counter evaluates to 1"
41+
(evaluates_to get_new_counter.term one.term)
42+
43+
let () =
44+
test "Get incremented counter evaluates to 2"
45+
(evaluates_to get_incremented_counter.term two.term)

0 commit comments

Comments
 (0)