Releases: lambdageek/unbound-generics
0.4.4
What's changed
- Add
Alpha
andSubst
instances forNonEmpty
. Thanks Brent Yorgey (byorgey) - Add GHC 9.8 to CI matrix
- Bump
base
>= 4.9 - Remove
tested-with: 7.x
inunbound-generics.cabal
. We removed CI testing with GHC 7.x last year. - Move GSubst from
Unbound.Generics.LocallyNameless.Subst
into a separateInternal
module that is exported. Now users can write their own generic traversals.
Thanks Bohdan Liesnikov (liesnikov) - Welcome Austin Erlandson (erlandsona) as a maintainer
Full Changelog: v0.4.3...v0.4.4
Version 0.4.3
What's Changed
- New function
instantiate
function that substitutes a list of terms for a collection of bound variables in a toplevelBind p t
term.
New functionsubstBind
operation that substitutes for the bound variable of aBind (Name a) t
term.
This is a specialization ofinstantiate
to the case where the pattern is a singleName a
- Expose
Rec
constructor of theRec
type and thectxLevel
function fromAlphaCtx
- Drop CI testing with GHC 7.10, add CI testing with GHC 9.4
- Fix compilation with
transformers >= 0.6
Full Changelog: v0.4.2...v0.4.3
Version 0.4.2
What's Changed
- This is a maintenance release that adds support for building with GHC 9.2
Full Changelog: v0.4.0...v0.4.2
Version 0.4.0
This release brings a bug fix that may be a breaking change for some ASTs, and a new combinator.
-
Fix an issue in substitution where traversal would not continue in
an AST node for whichisvar
orisCoerceVar
is defined to return
non-Nothing
but which had additional structure.For example, in a language with meta variables and explicit substitutions:
data Expr = ... -- normal variables that stand for expressions | Var (Name Expr) -- a meta variable occurrence and an explicit substitution -- of expressions to substitute in for the free variables | MetaVar (Name Meta) [(Name Expr, Expr)] -- a meta variable stands for an expression with some free term vars data Meta = MetaVar Expr -- substitution for a meta in an expression instance Subst Expr Meta where isCoerceVar (MetaVar u sub) = Just (SubstCoerce u (Just . applyExplicitSubst sub)) applyExplicitSubst :: [(Name Expr, Expr)] -> Meta -> Expr applyExplicitSubst s (MetaVar e) = substs s e
Given an expression
e1
defined asMetaVar "u" [("x", 10)]
, we may want to
substitute aMeta ("x" + "x")
for"u"
to get10 + 10
(that is, we replace"u"
by the expression"x" + "x"
and immediately apply the substitution10
for"x"
).Now suppose we have an expression
e2
defined asMetaVar "v" [("y", e1)]
(that is, an occurrence of meta var "v" together with a substitution ofe1
from above for"y"
). If we again try to substituteMeta ("x" + "x")
for"u"
ine2
, we would expect to getMetaVar "v" [("y", 10 + 10)]
(that is, since "v" is not equal to "u", we leave the meta var alone, but substitute for any occurrences of "u" in the explicit substitution, soe1
becomes10 + 10
as
before).The bug in previous versions of
unbound-generics
was that we would incorrectly leaveMetaVar "v" [("y", e1)]
unchanged as soon as we saw thatisCoerceVar (MetaVar "v" [("y", e1)])
returnedJust (SubstCoerce "u" ...)
where"u" /= "v"
.Thanks Reed Mullanix (TOTWBF) for finding and fixing this issue.
#26 -
New binding specification type
Ignore
.Any two
Ignore T
terms will always be alpha-equivalent to each other, will be considered to contain no variables, and will not have any substitution apply beneathIgnore
. Useful for attaching annotation terms to your AST.import Text.Parsec.Pos (SourcePos) data Expr = ... | Lambda (Ignore SourcePos) (Bind (Name Expr) Expr)
As expected, any two
Lambda
expressions will be considered alpha-equivalent even if they differ in source position.Note that the
Ignore
will block operations onName a
for alla
, which can be a little unexpected:data Ty = TyVar (Name Ty) | TyArr Ty Ty instance Subst Ty Ty where ... data Expr = ... | Var (Name Expr) | Lambda (Ignore Ty) (Bind (Name Expr) Expr) instance Subst Ty Expr
Applying a substitution of a type for a free type variable to a
Lambda
will not descend into theIgnore Ty
.Thanks Reed Mullanix (TOTWBF) for the new operation.
Version 0.3.4
This release is meant to be compatible with GHC-8.6.1 / containers-0.6
Version 0.3.3
Bump exceptions
bound to >= 0.8 && < 0.11
to allow exceptions-0.10.0
Version 0.3.2
- Bump
deepseq >= 1.4.0.0
remove benchmark dependency ondeepseq-generics
when building with GHC >= 7.10 - Tested with GHC 8.4.1
- Tested with GHC 8.2.2
- Compile with
-Wcompat
- Add
Semigroup
instances for all types that were previouslyMonoid
instances - Added more examples to the examples/ directory
- Added
exceptions
dependency andMonadThrow
,MonadCatch
,MonadMask
instances forFreshMT
andLFreshMT
.
Version 0.3.1
Compiled with GHC 8.0.1
Removed Generic a
constraint on Subst b (Name a)
instance
v0.2
- Make
Embed
an instance ofOrd
- Provide
NFData
instances for all the combinators.
Depend on 'deepseq' - Re-implement
freshen'
andgfreshen
using a free monad to give
GHC a chance to inline it all away. This changes the type of
gfreshen
. Major version bump.- Expose
FFM
,liftFFM
andretractFFM
- Expose
- Start benchmarking some of the operations (particularly
unbind
).
v0.1.2
- Added
Shift
type for lifting the scope of anEmbed
combinator up one binding level. - (in 0.1.1, which never went to Hackage) Added a
makeClosedAlpha
TH splice for making 'Alpha' instances for types that don't participate inAlpha
in a non-trivial way. A typeT
is trivial with respect toAlpha
if:- it cannot contain any names
- thus its
aeq
is just(==)
- and
open
andclose
are both identity operations.