Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module defines a variation of free scoped (relative) monads relying on the foil for the scope-safe efficient handling of the binders.
See description of the approach in «Free Foil: Generating Efficient and Scope-Safe Abstract Syntax».
Synopsis
- data ScopedAST (binder :: S -> S -> Type) (sig :: Type -> Type -> Type) (n :: S) where
- data AST (binder :: S -> S -> Type) (sig :: Type -> Type -> Type) (n :: S) where
- substitute :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o
- substituteRefreshed :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o
- refreshAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder) => Scope n -> AST binder sig n -> AST binder sig n
- refreshScopedAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n
- alphaEquivRefreshed :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool
- alphaEquiv :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool
- alphaEquivScoped :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n -> Bool
- unsafeEqAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig, UnifiablePattern binder, Distinct n, Distinct l) => AST binder sig n -> AST binder sig l -> Bool
- unsafeEqScopedAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig, UnifiablePattern binder, Distinct n, Distinct l) => ScopedAST binder sig n -> ScopedAST binder sig l -> Bool
- class ZipMatch (sig :: Type -> Type -> Type) where
- convertToAST :: forall (n :: S) sig rawIdent binder rawTerm rawPattern rawScopedTerm. (Distinct n, Bifunctor sig, Ord rawIdent, CoSinkable binder) => (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm)) -> (forall (x :: S) z. Distinct x => Scope x -> Map rawIdent (Name x) -> rawPattern -> (forall (y :: S). DExt x y => binder x y -> Map rawIdent (Name y) -> z) -> z) -> (rawScopedTerm -> rawTerm) -> Scope n -> Map rawIdent (Name n) -> rawTerm -> AST binder sig n
- convertToScopedAST :: forall (n :: S) sig rawIdent binder rawTerm rawPattern rawScopedTerm. (Distinct n, Bifunctor sig, Ord rawIdent, CoSinkable binder) => (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm)) -> (forall (x :: S) z. Distinct x => Scope x -> Map rawIdent (Name x) -> rawPattern -> (forall (y :: S). DExt x y => binder x y -> Map rawIdent (Name y) -> z) -> z) -> (rawScopedTerm -> rawTerm) -> Scope n -> Map rawIdent (Name n) -> (rawPattern, rawScopedTerm) -> ScopedAST binder sig n
- convertFromAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (forall (x :: S) (y :: S). (Int -> rawIdent) -> binder x y -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> AST binder sig n -> rawTerm
- convertFromScopedAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (forall (x :: S) (y :: S). (Int -> rawIdent) -> binder x y -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> ScopedAST binder sig n -> (rawPattern, rawScopedTerm)
Documentation
data ScopedAST (binder :: S -> S -> Type) (sig :: Type -> Type -> Type) (n :: S) where Source #
Scoped term under a (single) name binder.
data AST (binder :: S -> S -> Type) (sig :: Type -> Type -> Type) (n :: S) where Source #
A term, generated by a signature Bifunctor
sig
,
with (free) variables in scope n
.
Var :: forall (n :: S) (binder :: S -> S -> Type) (sig :: Type -> Type -> Type). Name n -> AST binder sig n | A (free) variable in scope |
Node :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S). sig (ScopedAST binder sig n) (AST binder sig n) -> AST binder sig n | A non-variable syntactic construction specified by the signature |
Instances
(Bifunctor sig, CoSinkable binder) => RelMonad Name (AST binder sig) Source # | |||||
Show (Expr n) Source # | Use | ||||
InjectName (AST binder sig) Source # | |||||
Defined in Control.Monad.Free.Foil | |||||
(Bifunctor sig, CoSinkable binder) => Sinkable (AST binder sig) Source # | |||||
Defined in Control.Monad.Free.Foil | |||||
Generic (AST binder sig n) Source # | |||||
Defined in Control.Monad.Free.Foil
| |||||
(forall (x :: S) (y :: S). NFData (binder x y), forall scope term. (NFData scope, NFData term) => NFData (sig scope term)) => NFData (AST binder sig n) Source # | |||||
Defined in Control.Monad.Free.Foil | |||||
type Rep (AST binder sig n) Source # | |||||
Defined in Control.Monad.Free.Foil type Rep (AST binder sig n) = D1 ('MetaData "AST" "Control.Monad.Free.Foil" "free-foil-0.1.0-7PHOjgygGpg7q7SlKctZqC" 'False) (C1 ('MetaCons "Var" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Name n))) :+: C1 ('MetaCons "Node" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (sig (ScopedAST binder sig n) (AST binder sig n))))) |
Substitution
substitute :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o Source #
Substitution for free (scoped monads).
substituteRefreshed :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o Source #
Substitution for free (scoped monads).
This is a version of substitute
that forces refreshing of all name binders,
resulting in a term with normalized binders:
substituteRefreshed scope subst = refreshAST scope . subtitute scope subst
In general, substitute
is more efficient since it does not always refresh binders.
\(\alpha\)-equivalence
refreshAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder) => Scope n -> AST binder sig n -> AST binder sig n Source #
Refresh (force) all binders in a term, minimizing the used indices.
refreshScopedAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n Source #
Similar to refreshAST
, but for scoped terms.
alphaEquivRefreshed :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool Source #
\(\alpha\)-equivalence check for two terms in one scope
via normalization of bound identifiers (via refreshAST
).
Compared to alphaEquiv
, this function may perform some unnecessary
changes of bound variables when the binders are the same on both sides.
alphaEquiv :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool Source #
\(\alpha\)-equivalence check for two terms in one scope
via unification of bound variables (via unifyNameBinders
).
Compared to alphaEquivRefreshed
, this function might skip unnecessary
changes of bound variables when both binders in two matching scoped terms coincide.
alphaEquivScoped :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n -> Bool Source #
Same as alphaEquiv
but for scoped terms.
Unsafe equality checks
unsafeEqAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig, UnifiablePattern binder, Distinct n, Distinct l) => AST binder sig n -> AST binder sig l -> Bool Source #
Unsafe equality check for two terms. This check ignores the possibility that two terms might have different scope extensions under binders (which might happen due to substitution under a binder in absence of name conflicts).
unsafeEqScopedAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig, UnifiablePattern binder, Distinct n, Distinct l) => ScopedAST binder sig n -> ScopedAST binder sig l -> Bool Source #
A version of unsafeEqAST
for scoped terms.
Syntactic matching (unification)
class ZipMatch (sig :: Type -> Type -> Type) where Source #
Perform one-level matching for the two (non-variable) terms.
:: sig scope term | Left non-variable term. |
-> sig scope' term' | Right non-variable term. |
-> Maybe (sig (scope, scope') (term, term')) |
Converting to and from free foil
Convert to free foil
:: forall (n :: S) sig rawIdent binder rawTerm rawPattern rawScopedTerm. (Distinct n, Bifunctor sig, Ord rawIdent, CoSinkable binder) | |
=> (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm)) | Unpeel one syntax node (or a variable) from a raw term. |
-> (forall (x :: S) z. Distinct x => Scope x -> Map rawIdent (Name x) -> rawPattern -> (forall (y :: S). DExt x y => binder x y -> Map rawIdent (Name y) -> z) -> z) | Convert raw pattern into a scope-safe pattern. |
-> (rawScopedTerm -> rawTerm) | Extract a term from a scoped term (or crash). |
-> Scope n | Resulting scope of the constructed term. |
-> Map rawIdent (Name n) | Known names of free variables in scope |
-> rawTerm | Raw term. |
-> AST binder sig n |
Convert a raw term into a scope-safe term.
:: forall (n :: S) sig rawIdent binder rawTerm rawPattern rawScopedTerm. (Distinct n, Bifunctor sig, Ord rawIdent, CoSinkable binder) | |
=> (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm)) | Unpeel one syntax node (or a variable) from a raw term. |
-> (forall (x :: S) z. Distinct x => Scope x -> Map rawIdent (Name x) -> rawPattern -> (forall (y :: S). DExt x y => binder x y -> Map rawIdent (Name y) -> z) -> z) | Convert raw pattern into a scope-safe pattern. |
-> (rawScopedTerm -> rawTerm) | Extract a term from a scoped term (or crash). |
-> Scope n | Resulting scope of the constructed term. |
-> Map rawIdent (Name n) | Known names of free variables in scope |
-> (rawPattern, rawScopedTerm) | A pair of a pattern and a corresponding scoped term. |
-> ScopedAST binder sig n |
Same as convertToAST
but for scoped terms.
Convert from free foil
:: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig | |
=> (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) | Peel back one layer of syntax. |
-> (rawIdent -> rawTerm) | Convert identifier into a raw variable term. |
-> (forall (x :: S) (y :: S). (Int -> rawIdent) -> binder x y -> rawPattern) | Convert scope-safe pattern into a raw pattern. |
-> (rawTerm -> rawScopedTerm) | Wrap raw term into a scoped term. |
-> (Int -> rawIdent) | Convert underlying integer identifier of a bound variable into a raw identifier. |
-> AST binder sig n | Scope-safe term. |
-> rawTerm |
Convert a scope-safe term back into a raw term.
:: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig | |
=> (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) | Peel back one layer of syntax. |
-> (rawIdent -> rawTerm) | Convert identifier into a raw variable term. |
-> (forall (x :: S) (y :: S). (Int -> rawIdent) -> binder x y -> rawPattern) | Convert scope-safe pattern into a raw pattern. |
-> (rawTerm -> rawScopedTerm) | Wrap raw term into a scoped term. |
-> (Int -> rawIdent) | Convert underlying integer identifier of a bound variable into a raw identifier. |
-> ScopedAST binder sig n | Scope-safe scoped term. |
-> (rawPattern, rawScopedTerm) |
Same as convertFromAST
but for scoped terms.