Created
November 9, 2021 19:18
-
-
Save EduardoRFS/0925cfb2d8d738aa6594a21b7048d592 to your computer and use it in GitHub Desktop.
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
module type Kind_1 = sig | |
type _ t | |
type content | |
type content_t | |
val to_a_t : content t -> content_t | |
val of_a_t : content_t -> content t | |
end | |
type 'a kind_1 = (module Kind_1 with type content = 'a) | |
module type Eq = sig | |
type a | |
type b | |
val to_b : a kind_1 -> b kind_1 | |
val to_a : b kind_1 -> a kind_1 | |
end | |
type ('a, 'b) eq = (module Eq with type a = 'a and type b = 'b) | |
let eq (type t) : (t, t) eq = | |
(module struct | |
type a = t | |
type b = t | |
let to_a x = x | |
let to_b x = x | |
end) | |
(* only needed because OCaml doesn't have recursive module type *) | |
module rec Nat_wrapper : sig | |
type o = | | |
type _ s = | | |
module type Nat = sig | |
type t | |
val match_ : | |
if_zero:(unit -> 'a) -> | |
if_succ:(unit -> (module Nat_wrapper.Succ with type t = t) -> 'a) -> | |
'a | |
end | |
type 'a nat = (module Nat with type t = 'a) | |
module type Succ = sig | |
type content | |
type t | |
val eq : (t, content s) eq | |
val content : (module Nat with type t = content) | |
end | |
type 'a succ = (module Succ with type t = 'a) | |
end = | |
Nat_wrapper | |
open Nat_wrapper | |
let zero : o nat = | |
(module struct | |
type t = o | |
let match_ ~if_zero ~if_succ:_ = if_zero () | |
end) | |
let succ (type a) (n : (module Nat with type t = a)) : a s nat = | |
(module struct | |
type t = a s | |
let match_ : | |
if_zero:(unit -> 'a) -> | |
if_succ:(unit -> (module Succ with type t = t) -> 'a) -> | |
'a = | |
fun ~if_zero:_ ~if_succ -> | |
if_succ () | |
(module struct | |
type content = a | |
type nonrec t = t | |
let eq = eq | |
let content = n | |
end) | |
end) | |
let rec to_int : type a. a nat -> int = | |
fun (module N) -> | |
N.match_ | |
~if_zero:(fun () -> 0) | |
~if_succ:(fun () (module Content) -> 1 + to_int Content.content) | |
let is_succ (type a) ((module N) : a nat) = | |
N.match_ ~if_zero:(fun () -> None) ~if_succ:(fun () succ -> Some succ) | |
let one = succ zero | |
let two = succ one | |
let () = | |
match is_succ zero with | |
| None -> print_endline "zero is not succ" | |
| Some _ -> print_endline "zero is succ???" | |
let () = | |
match is_succ two with | |
| None -> print_endline "two is not succ???" | |
| Some _ -> print_endline "two is succ" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment