Skip to content

Instantly share code, notes, and snippets.

@jonsterling
Last active October 10, 2016 21:31
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 jonsterling/6a8dfc6a36e5d6284d3d8204c7285de1 to your computer and use it in GitHub Desktop.
Save jonsterling/6a8dfc6a36e5d6284d3d8204c7285de1 to your computer and use it in GitHub Desktop.
signature THEORY =
sig
type sort
type term
structure Var :
sig
include ORDERED
val toString : t -> string
end
type var = Var.t
structure Env : DICT where type key = var
datatype closure = <: of term * closure Env.dict
type env = closure Env.dict
val fresh : unit -> var
val var : var -> sort -> term
val force : closure -> term
end
signature LCF =
sig
structure Th : THEORY
structure Tl : TELESCOPE
where type Label.t = Th.var
datatype 'a state = |> of 'a Tl.telescope * Th.term
type 'a isjdg =
{sort : 'a -> Th.sort,
subst : Th.env -> 'a -> 'a}
val map : ('a -> 'b) -> 'a state -> 'b state
val ret : 'a isjdg -> 'a -> 'a state
val mul : 'a isjdg -> 'a state state -> 'a state
end
signature LCF_UTIL =
sig
include LCF
type 'a tactic = 'a -> 'a state
(* refine subgoals simultaneously *)
val THEN : 'a isjdg -> 'a tactic * 'a tactic -> 'a tactic
(* refine sequentially / one subgoal at a time to take advantage of substitutions *)
val SEQ_THEN : 'a isjdg -> 'a tactic * 'a tactic -> 'a tactic
end
functor Lcf (Th : THEORY) : LCF =
struct
structure Th = Th
structure Tl = Telescope (Th.Var)
datatype 'a state = |> of 'a Tl.telescope * Th.term
infix |>
type 'a isjdg =
{sort : 'a -> Th.sort,
subst : Th.env -> 'a -> 'a}
fun map f (psi |> m) =
Tl.map f psi |> m
fun ret (kit : 'a isjdg) jdg =
let
val x = Th.fresh ()
in
Tl.singleton x jdg |> Th.var x (#sort kit jdg)
end
fun prepend psi (psi' |> ev) =
Tl.append psi psi' |> ev
structure MulMachine =
struct
open Th infix <:
type 'a mul = 'a Tl.telescope * Th.closure * 'a state Tl.telescope
fun init (psi |> ev) : 'a mul =
(Tl.empty, ev <: Th.Env.empty, psi)
datatype 'a step =
UNLOAD of 'a state
| STEP of 'a mul
fun step (kit : 'a isjdg) ((psi, cl, ppsi) : 'a mul) =
let
open Tl.ConsView
val ev <: env = cl
in
case out ppsi of
EMPTY => UNLOAD (psi |> Th.force cl)
| CONS (x, psix |> evx, ppsi') =>
let
val psix' = Tl.map (#subst kit env) psix
val psi' = Tl.append psi psix'
val env' = Th.Env.insert env x (evx <: env)
in
STEP (psi', ev <: env', ppsi')
end
end
end
fun mul kit =
let
open MulMachine
fun go m =
case step kit m of
UNLOAD st => st
| STEP m' => go m'
in
go o init
end
end
functor LcfUtil (Lcf : LCF) : LCF_UTIL =
struct
open Lcf
infix |>
fun bind (kit : 'b isjdg) (f : 'a -> 'b state) (st : 'a state) : 'b state =
mul kit (map f st)
type 'a tactic = 'a -> 'a state
fun label (psi |> m) =
Tl.foldr (fn (x, a, r) => Tl.cons x (x, a) r) Tl.empty psi |> m
fun subgoals (psi |> m) =
psi
fun bindDict (kit : 'a isjdg) (fs : 'a tactic Th.Env.dict) (st : 'a state) : 'a state =
bind kit (fn (x, a) => (Th.Env.lookup fs x handle _ => ret kit) a) (label st)
fun focus (kit : 'a isjdg) (x : Th.var) (f : 'a -> 'a state) (st : 'a state) : 'a state =
bindDict kit (Th.Env.insert Th.Env.empty x f) st
(* "sequential" Kleisli extension: refine one subgoal, propagate the results, refine another subgoal, etc. *)
fun seqBind (kit : 'a isjdg) (f : 'a tactic) (st : 'a state) : 'a state =
let
open Tl.ConsView
fun go psi =
case out psi of
EMPTY => (fn st => st)
| CONS (x, a, psi') => go psi' o focus kit x f
in
go (subgoals st) st
end
fun THEN kit (t1, t2) =
bind kit t2 o t1
fun SEQ_THEN kit (t1, t2) =
seqBind kit t2 o t1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment