Page
Library
Module
Module type
Parameter
Class
Class type
Source
Breaking changes:
.mli
file), and a guide for porting code is provided below.Other changes:
bindlib.opam
file using Dune..ml
file)..mli
file).unbind2_in
function (similar to unbind2
but with a context).unmbind2_in
function (similar to unmbind2
but with a context).free_vars
function to construct a context containing all the free variables in a boxed value.reserve_name
function to reserve a variable name in a context.Ctxt
that can be used to define a custom variable renaming policy, given a type of contexts and a few configurations.Note: only the printing code is broken, all the rest is fine.
To understand the problem, recall that variable substitutions does not perform any bound variable renaming in Bindlib. What used to be the case, was that the bound variable names were appropriately updated upon term construction. A term that was freshly constructed was hence guaranteed to be safe for printing, and thus it was advised to do a "cleanup" term traversal before printing (this was done by composing a user-defined boxing function of type t -> t Bindlib.box
, and the build-in Bindlib.unbox
function).
For example, with a type of the terms of the λ-calculus, that would be done as follows, using the appropriate smart constructors.
type term =
| Var of term Bindlib.var
| Abs of (term, term) Bindlib.binder
| App of term * term
let var = Bindlib.box_var
let abs = Bindlib.box_apply (fun b -> Abs(b))
let app = Bindlib.box_apply2 (fun t u -> App(t,u))
let rec box_term: term -> term Bindlib.box = fun t ->
match t with
| Var(x) -> var x
| Abs(b) -> abs (Bindlib.box_binder box_term b)
| App(t,u) -> app (box_term t) (box_term u)
(* DOES NOT GUARANTEE THAT THE OUTPUT TERM IS SAFE FOR PRINTING ANYMORE. *)
let cleanup: term -> term = fun t ->
Bindlib.unbox (box_term t)
(* Naive printing function assuming correct names. *)
let rec to_string: term -> string = fun t ->
match t with
| Var(x) -> Bindlib.name_of x
| Abs(b) -> let (x,t) = Bindlib.unbind b in
"λ" ^ Bindlib.name_of x ^ "." ^ to_string t
| App(t,u) -> "(" ^ to_string t ^ ") " ^ to_string u
(* BROKEN PRINTING FUNCTION AS OF BINDLIB VERSION 6.0.0. *)
let to_string t = to_string (cleanup t)
In this new version of Bindlib, a function that prints or displays a term must rely on a context (of type Bindlib.ctxt
) for free variables. All renaming is performed when introducing fresh variables to substitute binders using special functions like Bindlib.new_var_in
or Bindlib.unbind_in
, which take care of picking a fresh name and maintaining the context.
Going back to the λ-calculus, the printing function must become the following.
(** [to_string_in ctxt t] is safe for printing assuming that [ctxt] is a valid
context for [t] (i.e., it contains all of its free variables). *)
let rec to_string_in : ctxt -> term -> string = fun ctxt t ->
match t with
| Var(x) -> Bindlib.name_of x
| Abs(b) -> let (x,t,ctxt) = Bindlib.unbind_in ctxt b in
"λ" ^ Bindlib.name_of x ^ "." ^ to_string_in ctxt t
| App(t,u) -> "(" ^ to_string_in ctxt t ^ ") " ^ to_string_in ctxt u
(** [to_string t] is always safe for printing. *)
let to_string : term -> string = fun t ->
to_string_in (Bindlib.free_vars (box_term t)) t
In some situations where a form of context is required anyway (e.g., for doing type-checking), it might make sense to maintain a Bindlib context to avoid the cost of a call to box_term
at printing time. However, this also means that a small cost for maintaining names is payed early on.
Bug fixes:
new_var
function could lead to variables with the same unique identifier (fixed by an η-expansion).unmbind2
was called with multiple binders with different arities was not handled, which could lead to problems (fixed by raising Invalid_argument "Arity missmatch in unmbind2"
on an arity mismatch).eq_mbinder
function also suffered from the same problem as unmbind2
(fixed by returning false
on an arity mismatch).Other changes:
unmbind2
and eq_mbinder
.Breaking changes:
'a bindbox
into 'a box
.('a,'b) binder
type.bind
function (use bind_var
instead).mbind
function (use bind_mvar
instead).binder_compose_left
function.binder_compose_right
into binder_compose
.binder_from_fun
function (replaced by raw_binder
).mbinder_from_fun
function (replaced by raw_mbinder
).bind_in
function.box_of_var
function into box_var
.copy_var
to match new_var
.eq_binder
(not necessary anymore).eq_mbinder
(not necessary anymore).fixpoint
function (too specific, and expressible).is_substituted
function (semantics not clear).prefix_of
function (abstraction-breaking).suffix_of
function (abstraction-breaking).unbind
(not necessary anymore).unbind2
(not necessary anymore).unbind_in
(not necessary anymore).unmbind
(not necessary anymore).unmbind2
function (not necessary anymore).unmbind_in
(not necessary anymore).vbind
function (use bind_var
instead).Other changes:
box_binder
function (useful helper).box_mbinder
function (useful helper).mbinder_compose
function.raw_binder
function to construct binders "manually".raw_mbinder
function (similar to raw_binder
).uids_of
function (similar to uid_of
).Breaking changes:
free_of
function (users must now remember the injection).Other changes:
uid_of
function that can be used to obtain the unique identifier associated to a variable (useful for hashing).unbind2
function that destructs two binders at once with the same (fresh) variable.eq_binder
function for testing equality of binders given an equality function for the bodies.unmbind2
function (similar to unbind2
).eq_binder
function (similar to eq_binder
).is_substituted
function.Breaking changes:
f
into lift_box
in the signature of the Lift
functor.f
into lift_box
in the signature of the Lift2
functor.apply_in_box
function.list_vars
function.Other changes:
darcs
to git
.mbinder_from_fun
function (similar to binder_from_fun
).mbinder_occurs
function (similar to binder_occur
).mbinder_rank
function (similar to binder_rank
).suffix_of
function to query the suffix of a variable name.Breaking changes:
'a variable
type into 'a var
.'a mvariable
type into 'a mvar
.compare_variables
function into compare_vars
.eq_variables
function into eq_vars
.context
type into ctxt
.list_variables
function into list_vars
.Other changes:
prefix_of
function to query the prefix of a variable name.unmbind
function which destructs a multiple binder (like the unbind
function for binders).unbind_in
and unmbind_in
functions, which are similar to unbind
and unmbind
but work with a context.Bindlib_util
and Ptmap
modules (not meant to be exposed).Breaking changes:
int
) argument of the unsafe binder_from_fun
function, which also has now a different semantics.Other changes:
binder_from_fun
function (unsafe).box_apply4
function.Major cleanup/rewriting of the library by Rodolphe Lepigre. First version distributed via Opam.
All earlier versions of Bindlib were developed by Christophe Raffalli. A version for Haskell was even available at some point.