Skip to content

Instantly share code, notes, and snippets.

@marctrem
Created May 1, 2019 03:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marctrem/94cf483c2fdf216d1a5ee9466ab47a8e to your computer and use it in GitHub Desktop.
Save marctrem/94cf483c2fdf216d1a5ee9466ab47a8e to your computer and use it in GitHub Desktop.
Phantom Builder
#!/usr/bin/env ocaml
#use "topfind"
#thread
#require "core"
open Core
type name_unset
type name_set
type age_unset
type age_set
type t = {
name : string ;
age : int ;
}
module Builder : sig
type ('name, 'age) b
val empty : (name_unset, age_unset) b
val set_name : ('name, 'age) b -> name:string -> (name_set, 'age) b
val set_age : ('name, 'age) b -> age:int -> ('name, age_set) b
val build : (name_set, age_set) b -> t
end =
struct
type ('name, 'age) b = {
name : string option ;
age : int option ;
}
let empty = {
name = None ;
age = None ;
}
let set_name b ~name = {
b with
name = Some name
}
let set_age b ~age = {
b with
age = Some age
}
let build b : t =
{
name = Option.value_exn b.name ;
age = Option.value_exn b.age ;
}
end
let () =
let b = Builder.empty
|> Builder.set_age ~age:27
|> Builder.set_name ~name:"John Cena" in
let built = Builder.build b in
print_endline built.name
@marctrem
Copy link
Author

marctrem commented May 1, 2019

If you comment line 63, you get:

File "./phantom_builder.ml", line 65, characters 28-29:
Error: This expression has type (name_set, age_unset) Builder.b
       but an expression was expected of type (name_set, age_set) Builder.b
       Type age_unset is not compatible with type age_set```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment