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)) tIn 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.