{-# LANGUAGE PatternSynonyms #-}

-- | An efficient and easy-to-use library for defining datatypes with
-- binders, and automatically handling bound variables and
-- alpha-equivalence. It is based on <#GP1999 Gabbay and Pitts>'s
-- theory of nominal sets.
--
-- Users should only import the top-level module "Nominal", which
-- exports all the relevant functionality in a clean and abstract way.
-- Its submodules, such as "Nominal.Unsafe", are implementation
-- specific and subject to change, and should not normally be imported
-- by user code.

module Nominal (
  -- * Overview
  -- $OVERVIEW

  -- * Atoms
  -- ** Atom types
  -- $ATOMS
  Atom,
  AtomKind(..),
  AtomOfKind,
  Atomic,
  NameSuggestion,
  
  -- ** Creation of fresh atoms in a scope
  -- $FRESHNESS
  with_fresh,
  with_fresh_named,
  with_fresh_namelist,

  -- ** Creation of fresh atoms globally
  -- $GLOBAL_FRESHNESS
  fresh,
  fresh_named,
  fresh_namelist,

  -- $NOMINAL_ANCHOR
  
  -- * Nominal types
  -- $NOMINAL
  Nominal(..),
  NominalPermutation,
  Basic(..),
  
  -- * Binders
  Bind,
  -- ** Basic operations
  (.),
  pattern (:.),
  abst,
  open,
  merge,

  -- ** Convenience functions
  bind,
  bind_named,
  bind_namelist,

  -- ** The Bindable class
  -- $BINDABLE
  Bindable(..),
  NominalBinder,

  -- ** Non-binding patterns
  NoBind(..),
  nobinding,

  -- $CONDITION_ANCHOR
  
  -- * Pitt's freshness condition
  -- $CONDITION
  
  -- * Printing of nominal values
  -- $PRINTING
  open_for_printing,
  NominalSupport(..),
  Support,
  Literal(..),

  -- $NOMINALSHOW_ANCHOR

  -- * The NominalShow class
  -- $NOMINALSHOW
  NominalShow(..),
  nominal_show,
  nominal_showsPrec,

  -- $DERIVING_ANCHOR

  -- * Deriving generic instances
  -- $DERIVING

  -- $CUSTOM_ANCHOR

  -- * Defining custom instances
  -- $CUSTOM

  -- ** Basic types
  -- $CUSTOM_BASIC

  basic_action,
  basic_support,
  basic_showsPrecSup,
  basic_binding,
  
  -- ** Recursive types
  -- $CUSTOM_RECURSIVE
  
  -- * Miscellaneous
  (),
  module Nominal.Generic
  -- $GENERICS
  
  -- $RELATED_ANCHOR
  
  -- * Related Work
  -- $RELATED

  -- $REFERENCES_ANCHOR
  
  -- * Acknowledgements
  -- $ACKNOWLEDGEMENTS

  -- * References
  -- $REFERENCES
)
where

import Prelude hiding ((.))

import Nominal.ConcreteNames
import Nominal.Atom
import Nominal.Permutation
import Nominal.Nominal
import Nominal.NominalSupport
import Nominal.Bindable
import Nominal.Atomic
import Nominal.NominalShow
import Nominal.Generic

-- ----------------------------------------------------------------------

-- $OVERVIEW
-- 
-- We start with a minimal example. The following code defines a
-- datatype of untyped lambda terms, as well as a substitution
-- function. The important point is that the definition of lambda
-- terms is /automatically/ up to alpha-equivalence (i.e., up to
-- renaming of bound variables), and substitution is /automatically/
-- capture-avoiding. These details are handled by the "Nominal"
-- library and do not require any special programming by the user.
--
-- > {-# LANGUAGE DeriveGeneric #-}
-- > {-# LANGUAGE DeriveAnyClass #-}
-- >
-- > import Nominal
-- > import Prelude hiding ((.))
-- >
-- > -- Untyped lambda terms, up to alpha-equivalence.
-- > data Term = Var Atom | App Term Term | Abs (Bind Atom Term)
-- >   deriving (Generic, Nominal)
-- >
-- > -- Capture-avoiding substitution.
-- > subst :: Term -> Atom -> Term -> Term
-- > subst m z (Var x)
-- >   | x == z    = m
-- >   | otherwise = Var x
-- > subst m z (App t s) = App (subst m z t) (subst m z s)
-- > subst m z (Abs (x :. t)) = Abs (x . subst m z t)
--
-- Let us examine this code in more detail:
-- 
-- * The first four lines are boilerplate. Any code that uses the
-- "Nominal" library should enable the language options
-- @DeriveGeneric@ and @DeriveAnyClass@, and should import "Nominal".
-- We also hide the @(.)@ operator from the "Prelude", because the
-- "Nominal" library re-purposes the period as a binding operator.
--
-- * The next line defines the datatype @Term@ of untyped lambda
-- terms.  Here, 'Atom' is a predefined type of atomic /names/, which
-- we use as the names of variables. A term is either a variable, an
-- application, or an abstraction. The type @('Bind' 'Atom' Term)@ is
-- defined by the "Nominal" library and represents pairs (/a/,/t/) of
-- an atom and a term, modulo alpha-equivalence. We write /a/'.'/t/ to
-- denote such an alpha-equivalence class of pairs.
--
-- * The next line declares that @Term@ is a /nominal/ type, by
-- deriving an instance of the type class 'Nominal' (and also
-- 'Generic', which enables the magic that allows 'Nominal' instances
-- to be derived automatically).  In a nutshell, a nominal type is
-- a type that is aware of the existence of atoms. The 'Bind'
-- operation can only be applied to nominal types, because
-- otherwise alpha-equivalence would not make sense.
--
-- * The substitution function inputs a term /m/, a variable /z/, and
-- a term /t/, and outputs the term /t/[/m/\//z/] that is obtained
-- from /t/ by replacing all occurrences of the variable /z/ by /m/.
-- The clauses for variables and application are straightforward. Note
-- that atoms can be compared for equality. In the clause for
-- abstraction, @(x :. t)@ is an /abstraction pattern/. It matches any
-- abstraction of the form /y/'.'/s/, which is of type @('Bind' 'Atom'
-- Term)@. Moreover, each time the abstraction pattern is used, a
-- /fresh/ name /x/ and a term /t/ are generated such that /x/'.'/t/ =
-- /y/'.'/s/. Since the name /x/ resulting from the pattern matching
-- is always guaranteed to be fresh, the substitution can be
-- recursively applied to /t/ without the possibility that /x/ may be
-- captured in /m/ or that /x/ = /z/. In other words, abstraction
-- patterns implement what is informally known as
-- /Barendregt's variable convention/, i.e., the names of bound
-- variables are always assumed to be fresh.
--
-- See the folder
-- <http://hackage.haskell.org/package/nominal/src/examples/ \"examples\">
-- for additional examples.

-- ----------------------------------------------------------------------

-- $ATOMS
--
-- /Atoms/ are things that can be bound. The important properties of
-- atoms are: there are infinitely many of them (so we can always find
-- a fresh one), and atoms can be compared for equality. Atoms do not
-- have any other special properties, and in particular, they are
-- interchangeable (any atom is as good as any other atom).
--
-- As shown in the introductory example above, the type 'Atom' can be
-- used for this purpose. In addition, it is often useful to have more
-- than one kind of atoms (for example, term variables and type
-- variables), and/or to customize the default names that are used
-- when atoms of each kind are displayed (for example, to use /x/,
-- /y/, /z/ for term variables and α, β, γ for type variables).
--
-- The standard way to define an additional type of atoms is to define
-- a new empty type /t/ that is an instance of 'AtomKind'. Optionally,
-- a list of suggested names for the atoms can be provided. Then
-- 'AtomOfKind' /t/ is a new type of atoms. For example:
--
-- > data VarName
-- > instance AtomKind VarName where
-- >   suggested_names _ = ["x", "y", "z"]
-- > 
-- > newtype Variable = AtomOfKind VarName
-- 
-- All atom types are members of the type class 'Atomic'.

-- ----------------------------------------------------------------------

-- $FRESHNESS
--
-- Sometimes we need to generate a fresh atom.  In the "Nominal"
-- library, the philosophy is that a fresh atom is usually generated
-- for a particular /purpose/, and the use of the atom is local to
-- that purpose. Therefore, a fresh atom should always be generated
-- within a local /scope/. So instead of
--
-- > let a = fresh in something,
--
-- we write
--
-- > with_fresh (\a -> something).
--
-- To ensure soundness, the programmer must ensure that the fresh atom
-- does not escape the body of the 'with_fresh' block. See 
-- <#CONDITION "Pitts's freshness condition"> for examples
-- of what is and is not permitted, and a more precise statement of
-- the correctness condition.

-- ----------------------------------------------------------------------

-- $GLOBAL_FRESHNESS
--
-- Occasionally, it can be useful to generate a globally fresh atom.
-- This is done within the 'IO' monad, and therefore, the function
-- 'fresh' (and its friends) are /not/ subject to
-- <#CONDITION Pitts's freshness condition>.
-- 
-- These functions are primarily intended for testing. They
-- give the user a convenient way to generate fresh names in the
-- read-eval-print loop, for example:
--
-- >>> a <- fresh :: IO Atom
-- >>> b <- fresh :: IO Atom
-- >>> a.b.(a,b)
-- x . y . (x,y)
--
-- These functions should rarely be used in programs. Normally you
-- should use 'with_fresh' instead of 'fresh', to generate a fresh
-- atom in a specific scope for a specific purpose. If you find
-- yourself generating a lot of global names and not binding them,
-- consider whether the "Nominal" library is the wrong tool for your
-- purpose. Perhaps you should use "Data.Unique" instead?

-- ----------------------------------------------------------------------

-- $NOMINAL_ANCHOR #NOMINAL#

-- $NOMINAL
--
-- Informally, a type of /nominal/ if if is aware of the existence of
-- atoms, and knows what to do in case an atom needs to be renamed.
-- More formally, a type is nominal if it is acted upon by the group
-- of finitely supported permutations of atoms. Ideally, all types
-- are nominal.
--
-- When using the "Nominal" library, all types whose elements can
-- occur in the scope of a binder must be instances of the 'Nominal'
-- type class.  Fortunately, in most cases, new instances of 'Nominal'
-- can be derived automatically.

-- ----------------------------------------------------------------------

-- $BINDABLE
--
-- The 'Bindable' class contains things that can be abstracted. More
-- precisely, /x/ is /bindable/, or a /binder/, if abstractions of the
-- form /x/./t/ can be formed.  Sometimes binders are also called
-- /patterns/, but we avoid this terminology here, to avoid confusion
-- with pattern matching, which is a separate operation from binding.
--
-- In addition to atoms, binders include pairs of atoms, lists of
-- atoms, and so on.  In most cases, new instances of 'Bindable' can
-- be derived automatically.
-- 
-- For example, @(/x/,/y/)./t/@ binds a pair of atoms in /t/. It is
-- roughly equivalent to @/x/./y/./t/@, except that it is of type
-- 'Bind' ('Atom', 'Atom') /t/ instead of
-- 'Bind' 'Atom' ('Bind' 'Atom' /t/).
--
-- When a binder contains repeated atoms, they are regarded as
-- distinct, and are bound one at a time, in some fixed but
-- unspecified order. For example, @(/x/,/x/).(/x/,/x/)@ is equivalent
-- to either @(/x/,/y/).(/x/,/x/)@ or @(/x/,/y/).(/y/,/y/)@. Which of
-- the two alternatives is chosen is implementation specific and user
-- code should not rely on the order of abstractions in such cases.


-- ----------------------------------------------------------------------

-- $PRINTING
--
-- The printing of nominal values requires concrete names for the
-- bound variables to be chosen in such a way that they do not clash
-- with the names of any free variables, constants, or other bound
-- variables. This requires the ability to compute the set of free
-- atoms (and constants) of a term. We call this set the /support/ of
-- a term.
--
-- Our mechanism for pretty-printing nominal values consists of two
-- things: the type class 'NominalSupport', which represents terms
-- whose support can be calculated, and the function
-- 'open_for_printing', which handles choosing concrete names for
-- bound variables.
--
-- In addition to this general-purpose mechanism, there is also the
-- 'NominalShow' type class, which is analogous to 'Show' and provides
-- a default representation of nominal terms.

-- ----------------------------------------------------------------------

-- $NOMINALSHOW_ANCHOR #NOMINALSHOW#

-- $NOMINALSHOW
--
-- The 'NominalShow' class is analogous to Haskell's standard 'Show'
-- class, and provides a default method for converting elements of
-- nominal datatypes to strings. The function 'nominal_show' is
-- analogous to 'show'.  In most cases, new instances of 'NominalShow'
-- can be derived automatically.

-- ----------------------------------------------------------------------

-- $DERIVING_ANCHOR #DERIVING#

-- $DERIVING
--
-- In many cases, instances of 'Nominal', 'NominalSupport',
-- 'NominalShow', and/or 'Bindable' can be derived automatically, using
-- the generic \"@deriving@\" mechanism.  To do so, enable the
-- language options @DeriveGeneric@ and @DeriveAnyClass@, and derive a
-- 'Generic' instance in addition to whatever other instances you want
-- to derive.
--
-- ==== Example 1: Trees
--
-- > {-# LANGUAGE DeriveGeneric #-}
-- > {-# LANGUAGE DeriveAnyClass #-}
-- > 
-- > data MyTree a = Leaf | Branch a (MyTree a) (MyTree a)
-- >   deriving (Generic, Nominal, NominalSupport, NominalShow, Show, Bindable)
--
-- ==== Example 2: Untyped lambda calculus
--
-- Note that in the case of lambda terms, it does not make sense to
-- derive a 'Bindable' instance, as lambda terms cannot be used as
-- binders.
-- 
-- > {-# LANGUAGE DeriveGeneric #-}
-- > {-# LANGUAGE DeriveAnyClass #-}
-- > 
-- > data Term = Var Atom | App Term Term | Abs (Bind Atom Term)
-- >   deriving (Generic, Nominal, NominalSupport, NominalShow, Show)
--
-- == Deriving instances for existing types
--
-- Sometimes it may be necessary to derive an instance of 'Nominal' or
-- one of the other type classes for an already existing datatype.
-- This can be done by specifying an instance declaration without any
-- body. For example, here is how the instances would be specified for
-- the 'Maybe' type:
--
-- > instance (Nominal a) => Nominal (Maybe a)
-- > instance (NominalSupport a) => NominalSupport (Maybe a)
-- > instance (NominalShow a) => NominalShow (Maybe a)
-- > instance (Bindable a) => Bindable (Maybe a)

-- ----------------------------------------------------------------------

-- $CUSTOM_ANCHOR #CUSTOM#

-- $CUSTOM
-- 
-- There are some cases where instances of 'Nominal' and the other
-- type classes cannot be automatically derived. These include: (a)
-- base types such as 'Double', (b) types that are not generic, such
-- as certain GADTs, and (c) types that require a custom 'Nominal'
-- instance for some other reason (advanced users only!). In such
-- cases, instances must be defined explicitly. The follow examples
-- explain how this is done.

-- ----------------------------------------------------------------------

-- $CUSTOM_BASIC
--
-- A type is /basic/ or /non-nominal/ if its elements cannot contain
-- atoms. Typical examples are base types such as 'Integer' and
-- 'Bool', and other types constructed exclusively from them, such as
-- @['Integer']@ or @'Bool' -> 'Bool'@.
--
-- For basic types, it is very easy to define instances of 'Nominal',
-- 'NominalSupport', 'NominalShow', and 'Bindable': for each class
-- method, we provide a corresponding helper function whose name
-- starts with @basic_@ that does the correct thing. These functions
-- can only be used to define instances for /non-nominal/ types.
--
-- ==== Example
--
-- We show how the nominal type class instances for the base type
-- 'Double' were defined.
--
-- > instance Nominal Double where
-- >   (•) = basic_action
-- >
-- > instance NominalSupport Double where
-- >   support = basic_support
-- >
-- > instance NominalShow Double where
-- >   showsPrecSup = basic_showsPrecSup
-- >
-- > instance Bindable Double where
-- >   binding = basic_binding
--
-- An alternative to defining new basic type class instances is to
-- wrap the corresponding types in the constructor 'Basic'.  The type
-- @'Basic' MyType@ is isomorphic to @MyType@, and is automatically an
-- instance of the relevant type classes.

-- ----------------------------------------------------------------------

-- $CUSTOM_RECURSIVE
--
-- For recursive types, instances for nominal type classes can be
-- defined by passing the relevant operations recursively down the
-- term structure.  We will use the type @MyTree@ as a running
-- example.
-- 
-- > data MyTree a = Leaf | Branch a (MyTree a) (MyTree a)
--
-- ==== Nominal
-- 
-- To define an instance of 'Nominal', we must specify how
-- permutations of atoms act on the elements of the type. For example:
--
-- > instance (Nominal a) => Nominal (MyTree a) where
-- >   π • Leaf = Leaf
-- >   π • (Branch a l r) = Branch (π • a) (π • l) (π • r)
--
-- ==== NominalSupport
-- 
-- To define an instance of 'NominalSupport', we must compute the
-- support of each term. This can be done by applying 'support' to a
-- tuple or list (or combination thereof) of immediate subterms. For
-- example:
--
-- > instance (NominalSupport a) => NominalSupport (MyTree a) where
-- >   support Leaf = support ()
-- >   support (Branch a l r) = support (a, l, r)
--
-- Here is another example showing additional possibilities:
-- 
-- > instance NominalSupport Term where
-- >   support (Var x) = support x
-- >   support (App t s) = support (t, s)
-- >   support (Abs t) = support t
-- >   support (MultiApp t args) = support (t, [args])
-- >   support Unit = support ()
--
-- If your nominal type uses additional constants, identifiers, or
-- reserved keywords that are not implemented as 'Atom's, but whose
-- names you don't want to clash with the names of bound variables,
-- declare them with 'Literal' applied to a string:
--
-- >   support (Const str) = support (Literal str)
--
-- ==== NominalShow
--
-- Custom 'NominalShow' instances require a definition of the
-- 'showsPrecSup' function. This is very similar to the 'showsPrec'
-- function of the 'Show' class, except that the function takes the
-- term's support as an additional argument. Here is how it is done
-- for the @MyTree@ datatype:
-- 
-- > instance (NominalShow a) => NominalShow (MyTree a) where
-- >   showsPrecSup sup d Leaf = showString "Leaf"
-- >   showsPrecSup sup d (Branch a l r) =
-- >     showParen (d > 10) $
-- >       showString "Branch "
-- >       ∘ showsPrecSup sup 11 a
-- >       ∘ showString " "
-- >       ∘ showsPrecSup sup 11 l
-- >       ∘ showString " "
-- >       ∘ showsPrecSup sup 11 r
--
-- ==== Bindable
--
-- The 'Bindable' class requires a function 'binding', which maps a
-- term to the corresponding binder. The recursive cases use the
-- 'Applicative' structure of the 'NominalBinder' type. 
-- 
-- Here is how we could define a 'Bindable' instance for the
-- @MyTree@ type. We use the \"applicative do\" notation for
-- convenience, although this is not essential.
--
-- > {-# LANGUAGE ApplicativeDo #-}
-- > 
-- > instance (Bindable a) => Bindable (MyTree a) where
-- >   binding Leaf = do
-- >     pure Leaf
-- >   binding (Branch a l r) = do
-- >     a' <- binding a
-- >     l' <- binding l
-- >     r' <- binding r
-- >     pure (Branch a' l' r')
--
-- To embed non-binding sites within a binder, replace 'binding' by
-- 'nobinding' in the recursive call. For further discussion of
-- non-binding binders, see also 'NoBind'. Here is an example:
--
-- > {-# LANGUAGE ApplicativeDo #-}
-- > 
-- > data HalfBinder a b = HalfBinder a b
-- >
-- > instance (Bindable a) => Bindable (HalfBinder a b) where
-- >   binding (HalfBinder a b) = do
-- >     a' <- binding a
-- >     b' <- nobinding b
-- >     pure (HalfBinder a' b')
--
-- The effect of this is that the /a/ is bound and /b/ is not bound in
-- the term @(HalfBinder /a/ /b/)./t/@,
-- 

-- ----------------------------------------------------------------------

-- $CONDITION_ANCHOR #CONDITION#

-- $CONDITION
--
-- To ensure soundness (referential transparency and equivariance),
-- all functions that generate a fresh name in a local scope must
-- satisfy a certain condition known as Pitts's /freshness/
-- /condition/ /for/ /binders/ (see Chapter 4.5 of 
-- <#PITTS2013 [Pitts 2013]>).
--
-- Informally, this condition means that the fresh atom must not
-- escape the body of the block in which it was created. Thus, for
-- example, the following are permitted:
--   
-- > with_fresh (\a -> f a == g a)
-- > with_fresh (\a -> a . f a b c)
--
-- Here is an example of what is /not/ permitted:
--
-- > with_fresh (\a -> a)
--
-- In more technical terms, the correctness condition is that in an
-- application
--
-- > with_fresh (\a -> body),
--
-- we must have /a/ \# /body/.  See <#PITTS2003 [Pitts 2003]> or
-- <#PITTS2013 [Pitts 2013]> for more information on what this
-- means.
--
-- The following exported functions are subject to the freshness condition:
-- 'with_fresh', 
-- 'with_fresh_named', 
-- 'with_fresh_namelist',
-- 'open',
-- 'open_for_printing',
-- as well as the use of abstraction patterns @(@':.'@)@.
--
-- Haskell does not enforce this restriction. But if a program
-- violates it, referential transparency may not hold, which could in
-- theory lead to unsound compiler optimizations and undefined
-- behavior. Here is an example of an incorrect use of 'with_fresh'
-- that violates referential transparency:
-- 
-- >>> (with_fresh id :: Atom) == (with_fresh id :: Atom)
-- False

----------------------------------------------------------------------

-- $GENERICS
--
-- We re-export the "Generic" type class for convenience, so that
-- users do not have to import "GHC.Generics".

----------------------------------------------------------------------

-- $RELATED_ANCHOR #RELATED#

-- $RELATED
--
-- <#CHENEY2005 [Cheney 2005]> and
-- <#WYS2011 [Weirich, Yorgey, and Sheard 2011]> describe
-- Haskell implementations of binders using generic programming. While
-- there are many similarities, these implementations differ from the
-- "Nominal" library in several respects.
-- 
-- 1. /Higher-order nominal types./ Weirich et al.'s \"Unbound\"
-- library is based on the locally nameless approach, and therefore
-- function types cannot appear under binders. Although Cheney's
-- library is based on the nominal approach, it requires the
-- relation /a/ \# /t/ to be decidable for all nominal types, and
-- therefore function types cannot be nominal. In the "Nominal"
-- library, function types are nominal and can occur under binders.
--
-- 2. /Freshness monad vs. scoped freshness./ Both the libraries of
-- Cheney and Weirich et al. use a freshness monad; all operations
-- that create fresh names (such as 'open') take place in this monad.
-- While this is semantically sound, it has some disadvantages: (a)
-- Every computation with binders must be threaded through the monad.
-- When this is done deeply within a nested expression, this gives
-- rise to an unnatural programming style. (b) Computations must be
-- threaded through the monad even though the user is aware, in the
-- relevant use cases, that the defined functions are in fact pure
-- (i.e., the freshness state is inessential). (c) The use of a
-- freshness monad precludes the use of abstraction patterns. The
-- "Nominal" library uses /scoped freshness/ instead of a freshness
-- monad. This lends itself to a more natural programming style. The
-- price to pay for this is that the user must ensure that fresh names
-- are only used in the local scope in which they were
-- generated. Formally, the user must adhere to a correctness
-- criterion
-- (<#CONDITION Pitts's freshness condition>) that cannot be checked
-- by the compiler.
--
-- 3. /Simplicity./ Weirich et al.'s \"Unbound\" library has many
-- advanced features, such as set-binders, recursive patterns, nested
-- bindings, and an exposed interface for certain low-level atom
-- manipulations.  The "Nominal" library currently lacks these
-- features. Instead, it focuses on ease of use and an efficient
-- implementation of a core set of functionalities. The hope is that
-- these are sufficiently general and robust to permit more advanced
-- features to be implemented in user space on top of the library. It
-- remains to be seen whether this is the case.
--
-- <#SPG2003 [Shinwell, Pitts, and Gabbay 2003]> describe FreshML, an
-- extension of ML with binders. This was later implemented by
-- <#SP2005 [Shinwell and Pitts 2005]> as an extension of Objective
-- Caml. The functionality and philosophy of the "Nominal" library is
-- essentially similar to that of FreshML. Since ML is a
-- side-effecting language, the issue of a freshness monad does not
-- arise, but users must still adhere to
-- <#CONDITION Pitts's freshness condition> to guarantee that programs
-- define equivariant functions. However, since ML lacks Haskell's
-- support for generic programming and custom patterns, the FreshML
-- implementation requires patching the compiler. It is therefore
-- harder to deploy than a library.

----------------------------------------------------------------------

-- $ACKNOWLEDGEMENTS
--
-- Thanks to Frank Fu for stress-testing the library and insisting on
-- efficiency. Thanks to Andrew Pitts for helpful suggestions, and
-- especially for nudging me to implement abstraction patterns.

----------------------------------------------------------------------

-- $REFERENCES_ANCHOR #REFERENCES#

-- $REFERENCES
--
-- #CHENEY2005#
--
-- * J. Cheney. "Scrap your nameplate (functional pearl)". Proceedings
-- of the 10th ACM SIGPLAN International Conference on Functional
-- Programming (ICFP 2005), pages 180–191, 2005.
-- 
-- #GB1999#
-- 
-- * M. J. Gabbay and A. M. Pitts. "A new approach to abstract syntax
-- involving binders".  Proceedings of the 14th Annual IEEE Symposium
-- on Logic in Computer Science (LICS 1999), pages 214–224, 1999.
-- 
-- #PITTS2003#
--
-- * M. Pitts. "Nominal logic, a first order theory of names and
-- binding". Information and Computation 186:165–193, 2003.
--
-- #PITTS2013#
--
-- * M. Pitts. "Nominal sets: names and symmetry in computer
-- science". Cambridge University Press, 2013.
--
-- #SPG2003#
--
-- * M. R. Shinwell, A. M. Pitts, and M. J. Gabbay. "FreshML:
-- programming with binders made simple". Proceedings of the 8th ACM
-- SIGPLAN International Conference on Functional Programming (ICFP
-- 2003), pages 263–274, 2003.
--
-- #SP2005#
--
-- * M. R. Shinwell and A. M. Pitts. "Fresh Objective Caml user
-- manual". Technical Report 621, University of Cambridge Computer
-- Laboratory, February 2005. Implementation at
-- <https://www.cl.cam.ac.uk/~amp12/fresh-ocaml/>.
--
-- #WYS2011#
--
-- * S. Weirich, B. A. Yorgey, and T. Sheard. "Binders unbound".
-- Proceedings of the 16th ACM SIGPLAN International Conference on
-- Functional Programming (ICFP 2011), pages 333–345, 2011.
-- Implementation at <http://hackage.haskell.org/package/unbound>.