Breaking changes:
- Major change of semantics that impacts variable renaming (and printing). The
new semantics is explained in the documentation (see the
.mli
file), and a guide for porting code is provided below.
Other changes:
- Compilation using Dune.
- Generation of the
bindlib.opam
file using Dune. - Require at least OCaml 4.07.0 (not strictly necessary, but solves CI issues with the installation of Dune on older versions).
- Cleaning up of the documentation in the code (
.ml
file). - Polishing of the interface documentation (
.mli
file). - Add the
unbind2_in
function (similar tounbind2
but with a context). - Add the
unmbind2_in
function (similar tounmbind2
but with a context). - Add the
free_vars
function to construct a context containing all the free variables in a boxed value. - Add the
reserve_name
function to reserve a variable name in a context. - Add a functor
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:
- Partially-applied
new_var
function could lead to variables with the same unique identifier (fixed by an η-expansion). - The case where
unmbind2
was called with multiple binders with different arities was not handled, which could lead to problems (fixed by raisingInvalid_argument "Arity missmatch in unmbind2"
on an arity mismatch). - The
eq_mbinder
function also suffered from the same problem asunmbind2
(fixed by returningfalse
on an arity mismatch).
Other changes:
- Documentation update for
unmbind2
andeq_mbinder
.
Breaking changes:
- Rename type
'a bindbox
into'a box
. - Variance annotations removed on the
('a,'b) binder
type. - Remove the
bind
function (usebind_var
instead). - Remove the
mbind
function (usebind_mvar
instead). - Remove the (unsafe)
binder_compose_left
function. - Rename the (less unsafe)
binder_compose_right
intobinder_compose
. - Remove the (unsafe)
binder_from_fun
function (replaced byraw_binder
). - Remove the (unsafe)
mbinder_from_fun
function (replaced byraw_mbinder
). - Remove the
bind_in
function. - Rename the
box_of_var
function intobox_var
. - Change the order of arguments of
copy_var
to matchnew_var
. - Remove the first argument of
eq_binder
(not necessary anymore). - Remove the first argument of
eq_mbinder
(not necessary anymore). - Remove the
fixpoint
function (too specific, and expressible). - Remove the
is_substituted
function (semantics not clear). - Remove the
prefix_of
function (abstraction-breaking). - Remove the
suffix_of
function (abstraction-breaking). - Remove the first argument of
unbind
(not necessary anymore). - Remove the first argument of
unbind2
(not necessary anymore). - Remove the first argument of
unbind_in
(not necessary anymore). - Remove the first argument of
unmbind
(not necessary anymore). - Remove the first argument of
unmbind2
function (not necessary anymore). - Remove the first argument of
unmbind_in
(not necessary anymore). - Remove the
vbind
function (usebind_var
instead).
Other changes:
- Major improvement of the documentation, and description of the library in a paper.
- Add the
box_binder
function (useful helper). - Add the
box_mbinder
function (useful helper). - Add the (unsafe)
mbinder_compose
function. - Add the (unsafe)
raw_binder
function to construct binders "manually". - Add the (unsafe)
raw_mbinder
function (similar toraw_binder
). - Add the
uids_of
function (similar touid_of
).
Breaking changes:
- Remove the
free_of
function (users must now remember the injection).
Other changes:
- Add the (unsafe)
uid_of
function that can be used to obtain the unique identifier associated to a variable (useful for hashing). - Add the
unbind2
function that destructs two binders at once with the same (fresh) variable. - Add the
eq_binder
function for testing equality of binders given an equality function for the bodies. - Add the
unmbind2
function (similar tounbind2
). - Add the
eq_binder
function (similar toeq_binder
). - Add the
is_substituted
function.
Breaking changes:
- Rename
f
intolift_box
in the signature of theLift
functor. - Rename
f
intolift_box
in the signature of theLift2
functor. - Remove the (unsafe)
apply_in_box
function. - Remove the (useless)
list_vars
function.
Other changes:
- Require at least OCaml 3.12.1.
- Major cleaning up and documentation effort.
- Move from
darcs
togit
. - Add the
mbinder_from_fun
function (similar tobinder_from_fun
). - Add the
mbinder_occurs
function (similar tobinder_occur
). - Add the
mbinder_rank
function (similar tobinder_rank
). - Add the
suffix_of
function to query the suffix of a variable name.
Breaking changes:
- Rename the
'a variable
type into'a var
. - Rename the
'a mvariable
type into'a mvar
. - Rename the
compare_variables
function intocompare_vars
. - Rename the
eq_variables
function intoeq_vars
. - Rename the
context
type intoctxt
. - Rename the
list_variables
function intolist_vars
.
Other changes:
- Add the
prefix_of
function to query the prefix of a variable name. - Add the
unmbind
function which destructs a multiple binder (like theunbind
function for binders). - Add the
unbind_in
andunmbind_in
functions, which are similar tounbind
andunmbind
but work with a context. - Remove the
Bindlib_util
andPtmap
modules (not meant to be exposed).
Breaking changes:
- Remove the second (
int
) argument of the unsafebinder_from_fun
function, which also has now a different semantics.
Other changes:
- Document the
binder_from_fun
function (unsafe). - Add the
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.