| Portability | non-portable (-XKitchenSink) |
|---|---|
| Stability | experimental |
| Maintainer | Stephanie Weirich <sweirich@cis.upenn.edu> |
Generics.RepLib.Bind.LocallyNameless
Contents
Description
A generic implementation of name binding functions using a locally nameless representation. Datatypes with binding can be defined using the Name and Bind types. Expressive patterns for binding come from the Annot and Rebind types.
Important classes are:
Name generation is controlled via monads which implement the Fresh and LFresh classes.
- data Name a
- data AnyName = forall a . Rep a => AnyName (Name a)
- data Bind a b
- newtype Annot a = Annot a
- data Rebind a b
- integer2Name :: Rep a => Integer -> Name a
- string2Name :: Rep a => String -> Name a
- makeName :: Rep a => String -> Integer -> Name a
- name2Integer :: Name a -> Integer
- name2String :: Name a -> String
- anyName2Integer :: AnyName -> Integer
- anyName2String :: AnyName -> String
- name1 :: Rep a => Name a
- name2 :: Rep a => Name a
- name3 :: Rep a => Name a
- name4 :: Rep a => Name a
- name5 :: Rep a => Name a
- name6 :: Rep a => Name a
- name7 :: Rep a => Name a
- name8 :: Rep a => Name a
- name9 :: Rep a => Name a
- name10 :: Rep a => Name a
- class (Show a, Rep1 AlphaD a) => Alpha a where
- swaps' :: AlphaCtx -> Perm AnyName -> a -> a
- fv' :: AlphaCtx -> a -> Set AnyName
- lfreshen' :: LFresh m => AlphaCtx -> a -> (a -> Perm AnyName -> m b) -> m b
- freshen' :: Fresh m => AlphaCtx -> a -> m (a, Perm AnyName)
- match' :: AlphaCtx -> a -> a -> Maybe (Perm AnyName)
- close :: Alpha b => AlphaCtx -> b -> a -> a
- open :: Alpha b => AlphaCtx -> b -> a -> a
- nthpatrec :: a -> Integer -> (Integer, Maybe AnyName)
- findpatrec :: a -> AnyName -> (Integer, Bool)
- swaps :: Alpha a => Perm AnyName -> a -> a
- swapsAnnots :: Alpha a => Perm AnyName -> a -> a
- swapsBinders :: Alpha a => Perm AnyName -> a -> a
- match :: Alpha a => a -> a -> Maybe (Perm AnyName)
- matchAnnots :: Alpha a => a -> a -> Maybe (Perm AnyName)
- matchBinders :: Alpha a => a -> a -> Maybe (Perm AnyName)
- fv :: (Rep b, Alpha a) => a -> Set (Name b)
- patfv :: (Rep a, Alpha b) => b -> Set (Name a)
- binders :: (Rep a, Alpha b) => b -> Set (Name a)
- aeq :: Alpha a => a -> a -> Bool
- aeqBinders :: Alpha a => a -> a -> Bool
- bind :: (Alpha b, Alpha c) => b -> c -> Bind b c
- unsafeUnBind :: (Alpha a, Alpha b) => Bind a b -> (a, b)
- class Monad m => Fresh m where
- freshen :: (Fresh m, Alpha a) => a -> m (a, Perm AnyName)
- unbind :: (Fresh m, Alpha b, Alpha c) => Bind b c -> m (b, c)
- unbind2 :: (Fresh m, Alpha b, Alpha c, Alpha d) => Bind b c -> Bind b d -> m (Maybe (b, c, d))
- unbind3 :: (Fresh m, Alpha b, Alpha c, Alpha d, Alpha e) => Bind b c -> Bind b d -> Bind b e -> m (Maybe (b, c, d, e))
- class HasNext m where
- nextInteger :: m Integer
- resetNext :: Integer -> m ()
- class Monad m => LFresh m where
- lfreshen :: (Alpha a, LFresh m) => a -> (a -> Perm AnyName -> m b) -> m b
- lunbind :: (LFresh m, Alpha a, Alpha b) => Bind a b -> ((a, b) -> m c) -> m c
- lunbind2 :: (LFresh m, Alpha b, Alpha c, Alpha d) => Bind b c -> Bind b d -> (Maybe (b, c, d) -> m e) -> m e
- lunbind3 :: (LFresh m, Alpha b, Alpha c, Alpha d, Alpha e) => Bind b c -> Bind b d -> Bind b e -> (Maybe (b, c, d, e) -> m f) -> m f
- rebind :: (Alpha a, Alpha b) => a -> b -> Rebind a b
- reopen :: (Alpha a, Alpha b) => Rebind a b -> (a, b)
- class Rep1 (SubstD b) a => Subst b a where
- abs_swaps :: t -> t1 -> t2 -> t2
- abs_fv :: t -> t1 -> Set a
- abs_freshen :: Monad m => t -> t1 -> m (t1, Perm a)
- abs_match :: Eq a => t -> a -> a -> Maybe (Perm a1)
- abs_nthpatrec :: t -> t1 -> (t1, Maybe a)
- abs_findpatrec :: Num a => t -> t1 -> (a, Bool)
- abs_close :: t -> t1 -> t2 -> t2
- abs_open :: t -> t1 -> t2 -> t2
- data AlphaCtx
- matchR1 :: R1 AlphaD a -> AlphaCtx -> a -> a -> Maybe (Perm AnyName)
- rName :: forall a[aKgL]. Rep a[aKgL] => R (Name a[aKgL])
- rBind :: forall a[aKgI] b[aKgJ]. (Rep a[aKgI], Rep b[aKgJ]) => R (Bind a[aKgI] b[aKgJ])
- rRebind :: forall a[aKgD] b[aKgE]. (Rep a[aKgD], Rep b[aKgE]) => R (Rebind a[aKgD] b[aKgE])
- rAnnot :: forall a[aKgF]. Rep a[aKgF] => R (Annot a[aKgF])
Basic types
Names are things that get bound. This type is intentionally abstract; to create a Name you can use string2Name or integer2Name. The type parameter is a tag, or sort, which tells us what sorts of things this name may stand for. The sort must be an instance of the Rep type class.
A name with a hidden (existentially quantified) sort.
The type of a binding. We can Bind an a object in a b object if we can create "fresh" a objects, and a objects can occur unbound in b objects. Often a is Name but that need not be the case.
Like Name, Bind is also abstract. You can create bindings using bind and take them apart with unbind and friends.
Instances
| (Rep a[aKgI], Rep b[aKgJ], Sat (ctx[aKnS] a[aKgI]), Sat (ctx[aKnS] b[aKgJ])) => Rep1 ctx[aKnS] (Bind a[aKgI] b[aKgJ]) | |
| (Subst c b, Subst c a, Alpha a, Alpha b) => Subst c (Bind a b) | |
| (Alpha a, Alpha b, Read a, Read b) => Read (Bind a b) | The |
| (Show a, Show b) => Show (Bind a b) | |
| (Rep a[aKgI], Rep b[aKgJ]) => Rep (Bind a[aKgI] b[aKgJ]) | |
| (Alpha a, Alpha b) => Alpha (Bind a b) |
An annotation is a "hole" in a pattern where variables can be used, but not bound. For example, patterns may include type annotations, and those annotations can reference variables without binding them. Annotations do nothing special when they appear elsewhere in terms.
Constructors
| Annot a |
Rebind supports "telescopes" --- that is, patterns where bound variables appear in multiple subterms.
Instances
| (Rep a[aKgD], Rep b[aKgE], Sat (ctx[aKn5] a[aKgD]), Sat (ctx[aKn5] b[aKgE])) => Rep1 ctx[aKn5] (Rebind a[aKgD] b[aKgE]) | |
| (Subst c b, Subst c a, Alpha a, Alpha b) => Subst c (Rebind a b) | |
| (Alpha a, Alpha b, Eq b) => Eq (Rebind a b) | Compare for alpha-equality. |
| (Show a, Show b) => Show (Rebind a b) | |
| (Rep a[aKgD], Rep b[aKgE]) => Rep (Rebind a[aKgD] b[aKgE]) | |
| (Alpha a, Alpha b) => Alpha (Rebind a b) |
Utilities
makeName :: Rep a => String -> Integer -> Name aSource
Create a Name from a String and an Integer index.
name2Integer :: Name a -> IntegerSource
Get the integer index of a Name.
name2String :: Name a -> StringSource
Get the string part of a Name.
anyName2Integer :: AnyName -> IntegerSource
Get the integer index of an AnyName.
anyName2String :: AnyName -> StringSource
Get the string part of an AnyName.
The Alpha class
class (Show a, Rep1 AlphaD a) => Alpha a whereSource
The Alpha type class is for types which may contain names. The Rep1 constraint means that we can only make instances of this class for types that have generic representations (which can be automatically derived by RepLib.)
Note that the methods of Alpha should never be called directly! Instead, use other methods provided by this module which are defined in terms of Alpha methods. (The only reason they are exported is to make them available to automatically-generated code.)
Most of the time, the default definitions of these methods will suffice, so you can make an instance for your data type by simply declaring
instance Alpha MyType
Methods
swaps' :: AlphaCtx -> Perm AnyName -> a -> aSource
See swaps.
fv' :: AlphaCtx -> a -> Set AnyNameSource
See fv.
lfreshen' :: LFresh m => AlphaCtx -> a -> (a -> Perm AnyName -> m b) -> m bSource
See lfreshen.
freshen' :: Fresh m => AlphaCtx -> a -> m (a, Perm AnyName)Source
See freshen.
match' :: AlphaCtx -> a -> a -> Maybe (Perm AnyName)Source
close :: Alpha b => AlphaCtx -> b -> a -> aSource
Replace free names by bound names.
open :: Alpha b => AlphaCtx -> b -> a -> aSource
Replace bound names by free names.
nthpatrec :: a -> Integer -> (Integer, Maybe AnyName)Source
looks up the nthpatrec b nnth name in the pattern b (zero-indexed), returning the number of names encountered if not found.
findpatrec :: a -> AnyName -> (Integer, Bool)Source
Instances
| Alpha Bool | |
| Alpha Char | |
| Alpha Double | |
| Alpha Float | |
| Alpha Int | |
| Alpha Integer | |
| Alpha () | |
| Alpha AnyName | |
| Alpha Exp | |
| Alpha a => Alpha [a] | |
| Alpha a => Alpha (Maybe a) | |
| Rep a => Alpha (R a) | |
| Alpha a => Alpha (Annot a) | |
| Rep a => Alpha (Name a) | |
| (Alpha a, Alpha b) => Alpha (Either a b) | |
| (Alpha a, Alpha b) => Alpha (a, b) | |
| (Alpha a, Alpha b) => Alpha (Rebind a b) | |
| (Alpha a, Alpha b) => Alpha (Bind a b) | |
| (Alpha a, Alpha b, Alpha c) => Alpha (a, b, c) | |
| (Alpha a, Alpha b, Alpha c, Alpha d) => Alpha (a, b, c, d) | |
| (Alpha a, Alpha b, Alpha c, Alpha d, Alpha e) => Alpha (a, b, c, d, e) |
swapsAnnots :: Alpha a => Perm AnyName -> a -> aSource
Apply a permutation to the annotations in a pattern. Binding names are left alone by the permutation.
swapsBinders :: Alpha a => Perm AnyName -> a -> aSource
Apply a permutation to the binding variables in a pattern. Annotations are left alone by the permutation.
match :: Alpha a => a -> a -> Maybe (Perm AnyName)Source
Compare two data structures and produce a permutation of their Names that will make them alpha-equivalent to each other (Names that appear in annotations must match exactly). Return Nothing if no such renaming is possible. Note that two terms are alpha-equivalent if the empty permutation is returned.
matchAnnots :: Alpha a => a -> a -> Maybe (Perm AnyName)Source
Compare two patterns, ignoring the names of binders, and produce a permutation of their annotations to make them alpha-equivalent to eachother. Return Nothing if no such renaming is possible.
fv :: (Rep b, Alpha a) => a -> Set (Name b)Source
Calculate the free variables of a particular sort contained in a term.
patfv :: (Rep a, Alpha b) => b -> Set (Name a)Source
List variables of a particular sort that occur freely in annotations (not bindings).
binders :: (Rep a, Alpha b) => b -> Set (Name a)Source
List all the binding variables (of a particular sort) in a pattern.
aeqBinders :: Alpha a => a -> a -> BoolSource
Determine (alpha-)equivalence of patterns
Binding operations
bind :: (Alpha b, Alpha c) => b -> c -> Bind b cSource
A smart constructor for binders, also sometimes known as "close".
unsafeUnBind :: (Alpha a, Alpha b) => Bind a b -> (a, b)Source
A destructor for binders that does not guarantee fresh names for the binders.
The Fresh class
unbind :: (Fresh m, Alpha b, Alpha c) => Bind b c -> m (b, c)Source
Unbind (also known as "open") is the destructor for bindings. It ensures that the names in the binding are fresh.
unbind2 :: (Fresh m, Alpha b, Alpha c, Alpha d) => Bind b c -> Bind b d -> m (Maybe (b, c, d))Source
Unbind two terms with the same fresh names, provided the binders match.
unbind3 :: (Fresh m, Alpha b, Alpha c, Alpha d, Alpha e) => Bind b c -> Bind b d -> Bind b e -> m (Maybe (b, c, d, e))Source
The LFresh class
Type class for contexts which can generate new globally fresh integers.
class Monad m => LFresh m whereSource
This is the class of monads that support freshness in an (implicit) local scope. Generated names are fresh for the current local scope, but not globally fresh. This class has a basic instance based on the reader monad.
lfreshen :: (Alpha a, LFresh m) => a -> (a -> Perm AnyName -> m b) -> m bSource
"Locally" freshen a term. TODO: explain this type signature a bit better.
lunbind :: (LFresh m, Alpha a, Alpha b) => Bind a b -> ((a, b) -> m c) -> m cSource
Destruct a binding in an LFresh monad.
lunbind2 :: (LFresh m, Alpha b, Alpha c, Alpha d) => Bind b c -> Bind b d -> (Maybe (b, c, d) -> m e) -> m eSource
Unbind two terms with the same fresh names, provided the binders match.
lunbind3 :: (LFresh m, Alpha b, Alpha c, Alpha d, Alpha e) => Bind b c -> Bind b d -> Bind b e -> (Maybe (b, c, d, e) -> m f) -> m fSource
Unbind three terms with the same fresh names, provided the binders match.
Rebinding operations
reopen :: (Alpha a, Alpha b) => Rebind a b -> (a, b)Source
destructor for binding patterns, the names should have already been freshened.
Substitution
class Rep1 (SubstD b) a => Subst b a whereSource
The Subst class governs capture-avoiding substitution. To derive this class, you only need to indicate where the variables are in the data type, by overriding the method isvar.
Methods
isvar :: a -> Maybe (Name b, b -> a)Source
If the argument is a variable, return its name and a function to generate a substituted term. Return Nothing for non-variable arguments.
subst :: Name b -> b -> a -> aSource
substitutes subst nm sub tmsub for nm in tm.
substs :: [Name b] -> [b] -> a -> aSource
Perform several simultaneous substitutions.
Instances
| Subst b AnyName | |
| Subst b Double | |
| Subst b Float | |
| Subst b Integer | |
| Subst b Char | |
| Subst b () | |
| Subst b Bool | |
| Subst b Int | |
| Subst Exp Exp | |
| Subst c a => Subst c (Annot a) | |
| Subst c a => Subst c (Maybe a) | |
| Subst c a => Subst c [a] | |
| Rep a => Subst b (Name a) | |
| Rep a => Subst b (R a) | |
| (Subst c b, Subst c a, Alpha a, Alpha b) => Subst c (Rebind a b) | |
| (Subst c b, Subst c a, Alpha a, Alpha b) => Subst c (Bind a b) | |
| (Subst c a, Subst c b) => Subst c (Either a b) | |
| (Subst c a, Subst c b) => Subst c (a, b) | |
| (Subst c a, Subst c b, Subst c d) => Subst c (a, b, d) | |
| (Subst c a, Subst c b, Subst c d, Subst c e) => Subst c (a, b, d, e) | |
| (Subst c a, Subst c b, Subst c d, Subst c e, Subst c f) => Subst c (a, b, d, e, f) |
For abstract types
abs_freshen :: Monad m => t -> t1 -> m (t1, Perm a)Source
abs_nthpatrec :: t -> t1 -> (t1, Maybe a)Source
abs_findpatrec :: Num a => t -> t1 -> (a, Bool)Source
Advanced
Match returns a permutation ordering. Either the terms are known to be LT or GT, or there is some permutation that can make them equal to eachother data POrdering = PLT | PEq (Perm AnyName) | PGT
Many of the operations in the Alpha class take an AlphaCtx: stored information about the iteration as it progresses. This type is abstract, as classes that override these operations should just pass the context on.
Pay no attention to the man behind the curtain
These type representation objects are exported so they can be referenced by auto-generated code. Please pretend they do not exist.