Skip to content

Instantly share code, notes, and snippets.

@akabe
Created October 29, 2015 06:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akabe/a16ed3bf95cf0d47e040 to your computer and use it in GitHub Desktop.
Save akabe/a16ed3bf95cf0d47e040 to your computer and use it in GitHub Desktop.
Static size checking for lists (loaded from files) by generative phantom types (functor version)
(* http://akabe.github.io/2015/10/GenerativePhantomTypes *)
#load "str.cma";;
(** Loads a list of integers from a file of a given path (delimiters = spaces,
tabs, or line feeds). *)
let load_list fname =
let re = Str.regexp "[ \t]+" in
let oc = open_in fname in
let rec aux acc = try aux (input_line oc :: acc) with End_of_file -> acc in
aux []
|> List.rev_map (Str.split re)
|> List.flatten
|> List.map int_of_string
module SizedList : sig
type 'n sized_list (** a type of lists of length ['n] (['n] is a phantom type
parameter, i.e., it does not appear in the r.h.s. of
the type definition) *)
type z (** a phantom type corresponding to zero *)
type 'n s (** a phantom type corresponding to successor (['n + 1]) *)
val nil : z sized_list
val cons : int -> 'n sized_list -> 'n s sized_list
val hd : 'n s sized_list -> int
val tl : 'n s sized_list -> 'n sized_list
val map : (int -> int) -> 'n sized_list -> 'n sized_list
val add : 'n sized_list -> 'n sized_list -> 'n sized_list
(** This functor has a type like [string -> (exists n. n sized_list)]. *)
module Load () (X : sig val fname : string end) : sig
type n
val x : n sized_list
end
end = struct
type 'n sized_list = int list
type z
type 'n s
let nil = []
let cons x l = x :: l
let hd = List.hd
let tl = List.tl
let map = List.map
let add = List.map2 (+)
module Load () (X : sig val fname : string end) = struct
type n
let x = load_list X.fname
end
end
open SizedList
module M1 = Load()(struct let fname = "file" end) (* M1.x : M1.n sized_list *)
let y = map (fun a -> a * 2) M1.x (* y : M1.n sized_list *)
let z = add M1.x y (* well-typed because M1.x and y have the same length *)
module M2 = Load()(struct let fname = "file" end) (* M2.x : M2.n sized_list *)
let w = add M1.x M2.x (* ill-typed because M1.x and M2.x possibly have different
sizes (M1.n <> M2.n) *)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment