free-foil-0.4.0: Efficient Type-Safe Capture-Avoiding Substitution for Free (Scoped Monads)
Safe HaskellNone
LanguageHaskell2010

Control.Monad.Foil.Internal

Description

Main definitions of the foil that can be reused for specific implementations. This is an internal module, so it also contains implementation details of the foil.

The original description of this approach is described in the IFL 2022 paper by Maclaurin, Radul, and Paszke «The Foil: Capture-Avoiding Substitution With No Sharp Edges». This module also introduces CoSinkable class, generalizing handling of patterns, as described in «Free Foil: Generating Efficient and Scope-Safe Abstract Syntax».

Since the representation of scopes and substitutions is either IntMap or IntSet, many of the operations have a worst-case complexity of \(O(\min(n,W))\). This means that the operation can become linear in the size of the scope \(n\) with a maximum of \(W\), the number of bits in an Int (32 or 64).

Synopsis

Documentation

>>> :set -XDataKinds
>>> :set -XFlexibleContexts
>>> :set -Wno-simplifiable-class-constraints
>>> import qualified Data.Map as Map
>>> import qualified Data.IntSet as IntSet
>>> import Data.Bifunctor.Tannen

Safe types and operations

data S Source #

S is a data kind of scope indices.

Since: 0.0.1

Constructors

VoidS

VoidS is the only explicit scope available to the users, representing an empty scope. All other scopes are represented with type variables, bound in rank-2 polymophic functions like withFreshBinder.

Instances

Instances details
(SinkableK f, ExtractRenamingK i, ExtractRenamingK j) => GSinkableK (Field ((('Kon f :: Atom k (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Field ((('Kon f :: Atom k (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) as -> (forall (cs :: LoT k). RenamingsK as cs -> Field ((('Kon f :: Atom k (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) cs -> r) -> r Source #

(SinkableK f, ExtractRenamingK i) => GSinkableK (Field (('Kon f :: Atom k (S -> Type)) ':@: 'Var i) :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Field (('Kon f :: Atom k (S -> Type)) ':@: 'Var i) as -> (forall (cs :: LoT k). RenamingsK as cs -> Field (('Kon f :: Atom k (S -> Type)) ':@: 'Var i) cs -> r) -> r Source #

GSinkableK f => GSinkableK (Exists S f :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Exists S f as -> (forall (cs :: LoT k). RenamingsK as cs -> Exists S f cs -> r) -> r Source #

HasNameBinders f => GHasNameBinders (Field ((('Kon f :: Atom d (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) :: LoT d -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: LoT d). Field ((('Kon f :: Atom d (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: LoT d) (bs :: LoT d). Field ((('Kon f :: Atom d (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) as -> [RawName] -> (Field ((('Kon f :: Atom d (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) bs, [RawName]) Source #

SinkableK NameBinder Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (NameBinder :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (NameBinder :@@: cs) -> r) -> r Source #

SinkableK NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (NameBinderList :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (NameBinderList :@@: cs) -> r) -> r Source #

SinkableK NameBinders Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (NameBinders :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (NameBinders :@@: cs) -> r) -> r Source #

SinkableK U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (U2 :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (U2 :@@: cs) -> r) -> r Source #

SinkableK V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (V2 :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (V2 :@@: cs) -> r) -> r Source #

GenericK NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Associated Types

type RepK NameBinderList 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK NameBinderList = (((Var0 :: Atom (S -> S -> Type) S) :~~: (Var1 :: Atom (S -> S -> Type) S)) :=>: (U1 :: LoT (S -> S -> Type) -> Type)) :+: Exists S (Field ((NameBinder :$: (Var1 :: Atom (S -> S -> S -> Type) S)) ':@: (Var0 :: Atom (S -> S -> S -> Type) S)) :*: Field ((NameBinderList :$: (Var0 :: Atom (S -> S -> S -> Type) S)) ':@: (Var2 :: Atom (S -> S -> S -> Type) S)))

Methods

fromK :: forall (x :: LoT (S -> S -> Type)). (NameBinderList :@@: x) -> RepK NameBinderList x #

toK :: forall (x :: LoT (S -> S -> Type)). RepK NameBinderList x -> NameBinderList :@@: x #

GenericK U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Associated Types

type RepK U2 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK U2 = ((Var0 :: Atom (S -> S -> Type) S) :~~: (Var1 :: Atom (S -> S -> Type) S)) :=>: (U1 :: LoT (S -> S -> Type) -> Type)

Methods

fromK :: forall (x :: LoT (S -> S -> Type)). (U2 :@@: x) -> RepK U2 x #

toK :: forall (x :: LoT (S -> S -> Type)). RepK U2 x -> U2 :@@: x #

GenericK V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Associated Types

type RepK V2 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK V2 = V1 :: LoT (S -> S -> Type) -> Type

Methods

fromK :: forall (x :: LoT (S -> S -> Type)). (V2 :@@: x) -> RepK V2 x #

toK :: forall (x :: LoT (S -> S -> Type)). RepK V2 x -> V2 :@@: x #

ExtractRenamingK ('VZ :: TyVar (S -> xs) S) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

extractRenamingK :: forall (as :: LoT (S -> xs)) (bs :: LoT (S -> xs)). RenamingsK as bs -> Name (Interpret ('Var ('VZ :: TyVar (S -> xs) S)) as) -> Name (Interpret ('Var ('VZ :: TyVar (S -> xs) S)) bs) Source #

putBackRenamingK :: forall (c :: S) (as :: LoT (S -> xs)) (bs :: LoT (S -> xs)). (Name (Interpret ('Var ('VZ :: TyVar (S -> xs) S)) as) -> Name c) -> RenamingsK as bs -> RenamingsK as (PutBackLoT ('VZ :: TyVar (S -> xs) S) c bs) Source #

SinkableK (f a) => GSinkableK (Field ((('Kon f :: Atom (S -> xs) (k1 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k1)) ':@: (Var0 :: Atom (S -> xs) S)) :: LoT (S -> xs) -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT (S -> xs)) (bs :: LoT (S -> xs)) r. RenamingsK as bs -> Field ((('Kon f :: Atom (S -> xs) (k1 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k1)) ':@: (Var0 :: Atom (S -> xs) S)) as -> (forall (cs :: LoT (S -> xs)). RenamingsK as cs -> Field ((('Kon f :: Atom (S -> xs) (k1 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k1)) ':@: (Var0 :: Atom (S -> xs) S)) cs -> r) -> r Source #

SinkableK (f a b) => GSinkableK (Field (((('Kon f :: Atom (S -> xs) (k2 -> k3 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k2)) ':@: ('Kon b :: Atom (S -> xs) k3)) ':@: (Var0 :: Atom (S -> xs) S)) :: LoT (S -> xs) -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT (S -> xs)) (bs :: LoT (S -> xs)) r. RenamingsK as bs -> Field (((('Kon f :: Atom (S -> xs) (k2 -> k3 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k2)) ':@: ('Kon b :: Atom (S -> xs) k3)) ':@: (Var0 :: Atom (S -> xs) S)) as -> (forall (cs :: LoT (S -> xs)). RenamingsK as cs -> Field (((('Kon f :: Atom (S -> xs) (k2 -> k3 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k2)) ':@: ('Kon b :: Atom (S -> xs) k3)) ':@: (Var0 :: Atom (S -> xs) S)) cs -> r) -> r Source #

GenericK (AST binder sig :: S -> Type) Source # 
Instance details

Defined in Control.Monad.Free.Foil

Associated Types

type RepK (AST binder sig :: S -> Type) 
Instance details

Defined in Control.Monad.Free.Foil

type RepK (AST binder sig :: S -> Type) = Field (Name :$: (Var0 :: Atom (S -> Type) S)) :+: Field ((sig :$: (((('Kon ScopedAST :: Atom (S -> Type) ((S -> S -> Type) -> (Type -> Type -> Type) -> S -> Type)) ':@: ('Kon binder :: Atom (S -> Type) (S -> S -> Type))) ':@: ('Kon sig :: Atom (S -> Type) (Type -> Type -> Type))) ':@: (Var0 :: Atom (S -> Type) S))) ':@: (((('Kon AST :: Atom (S -> Type) ((S -> S -> Type) -> (Type -> Type -> Type) -> S -> Type)) ':@: ('Kon binder :: Atom (S -> Type) (S -> S -> Type))) ':@: ('Kon sig :: Atom (S -> Type) (Type -> Type -> Type))) ':@: (Var0 :: Atom (S -> Type) S)))

Methods

fromK :: forall (x :: LoT (S -> Type)). (AST binder sig :@@: x) -> RepK (AST binder sig) x #

toK :: forall (x :: LoT (S -> Type)). RepK (AST binder sig) x -> AST binder sig :@@: x #

GenericK (ScopedAST binder sig :: S -> Type) Source # 
Instance details

Defined in Control.Monad.Free.Foil

Associated Types

type RepK (ScopedAST binder sig :: S -> Type) 
Instance details

Defined in Control.Monad.Free.Foil

type RepK (ScopedAST binder sig :: S -> Type) = Exists S (Field ((('Kon binder :: Atom (S -> S -> Type) (S -> S -> Type)) ':@: (Var1 :: Atom (S -> S -> Type) S)) ':@: (Var0 :: Atom (S -> S -> Type) S)) :*: Field (((('Kon AST :: Atom (S -> S -> Type) ((S -> S -> Type) -> (Type -> Type -> Type) -> S -> Type)) ':@: ('Kon binder :: Atom (S -> S -> Type) (S -> S -> Type))) ':@: ('Kon sig :: Atom (S -> S -> Type) (Type -> Type -> Type))) ':@: (Var0 :: Atom (S -> S -> Type) S)))

Methods

fromK :: forall (x :: LoT (S -> Type)). (ScopedAST binder sig :@@: x) -> RepK (ScopedAST binder sig) x #

toK :: forall (x :: LoT (S -> Type)). RepK (ScopedAST binder sig) x -> ScopedAST binder sig :@@: x #

ExtractRenamingK x2 => ExtractRenamingK ('VS x2 :: TyVar (x1 -> xs) S) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

extractRenamingK :: forall (as :: LoT (x1 -> xs)) (bs :: LoT (x1 -> xs)). RenamingsK as bs -> Name (Interpret ('Var ('VS x2 :: TyVar (x1 -> xs) S)) as) -> Name (Interpret ('Var ('VS x2 :: TyVar (x1 -> xs) S)) bs) Source #

putBackRenamingK :: forall (c :: S) (as :: LoT (x1 -> xs)) (bs :: LoT (x1 -> xs)). (Name (Interpret ('Var ('VS x2 :: TyVar (x1 -> xs) S)) as) -> Name c) -> RenamingsK as bs -> RenamingsK as (PutBackLoT ('VS x2 :: TyVar (x1 -> xs) S) c bs) Source #

(Functor f, Sinkable e) => Sinkable (Compose f e) Source #

A container of sinkable expressions is sinkable, elementwise.

The point of this instance is sinkContainer: since the proof typechecks, sinking the whole container is a coercion, and does not walk its spine.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> Compose f e n -> Compose f e l Source #

type RepK NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK NameBinderList = (((Var0 :: Atom (S -> S -> Type) S) :~~: (Var1 :: Atom (S -> S -> Type) S)) :=>: (U1 :: LoT (S -> S -> Type) -> Type)) :+: Exists S (Field ((NameBinder :$: (Var1 :: Atom (S -> S -> S -> Type) S)) ':@: (Var0 :: Atom (S -> S -> S -> Type) S)) :*: Field ((NameBinderList :$: (Var0 :: Atom (S -> S -> S -> Type) S)) ':@: (Var2 :: Atom (S -> S -> S -> Type) S)))
type RepK U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK U2 = ((Var0 :: Atom (S -> S -> Type) S) :~~: (Var1 :: Atom (S -> S -> Type) S)) :=>: (U1 :: LoT (S -> S -> Type) -> Type)
type RepK V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK V2 = V1 :: LoT (S -> S -> Type) -> Type
type RepK (AST binder sig :: S -> Type) Source # 
Instance details

Defined in Control.Monad.Free.Foil

type RepK (AST binder sig :: S -> Type) = Field (Name :$: (Var0 :: Atom (S -> Type) S)) :+: Field ((sig :$: (((('Kon ScopedAST :: Atom (S -> Type) ((S -> S -> Type) -> (Type -> Type -> Type) -> S -> Type)) ':@: ('Kon binder :: Atom (S -> Type) (S -> S -> Type))) ':@: ('Kon sig :: Atom (S -> Type) (Type -> Type -> Type))) ':@: (Var0 :: Atom (S -> Type) S))) ':@: (((('Kon AST :: Atom (S -> Type) ((S -> S -> Type) -> (Type -> Type -> Type) -> S -> Type)) ':@: ('Kon binder :: Atom (S -> Type) (S -> S -> Type))) ':@: ('Kon sig :: Atom (S -> Type) (Type -> Type -> Type))) ':@: (Var0 :: Atom (S -> Type) S)))
type RepK (ScopedAST binder sig :: S -> Type) Source # 
Instance details

Defined in Control.Monad.Free.Foil

type RepK (ScopedAST binder sig :: S -> Type) = Exists S (Field ((('Kon binder :: Atom (S -> S -> Type) (S -> S -> Type)) ':@: (Var1 :: Atom (S -> S -> Type) S)) ':@: (Var0 :: Atom (S -> S -> Type) S)) :*: Field (((('Kon AST :: Atom (S -> S -> Type) ((S -> S -> Type) -> (Type -> Type -> Type) -> S -> Type)) ':@: ('Kon binder :: Atom (S -> S -> Type) (S -> S -> Type))) ':@: ('Kon sig :: Atom (S -> S -> Type) (Type -> Type -> Type))) ':@: (Var0 :: Atom (S -> S -> Type) S)))

newtype Scope (n :: S) Source #

A safe scope, indexed by a type-level scope index n.

Since: 0.0.1

Constructors

UnsafeScope RawScope 

Instances

Instances details
NFData (Scope n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

rnf :: Scope n -> () #

newtype Name (n :: S) Source #

A name in a safe scope, indexed by a type-level scope index n.

Since: 0.0.1

Constructors

UnsafeName RawName 

Instances

Instances details
AlphaEquiv Name Source #

A name is α-equivalent only to itself.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

alphaEquivIn :: forall (n :: S). Distinct n => Scope n -> Name n -> Name n -> Bool Source #

Sinkable Name Source #

Sinking a Name is as simple as applying the renaming.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> Name n -> Name l Source #

SinkableK Name Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> Type)) (bs :: LoT (S -> Type)) r. RenamingsK as bs -> (Name :@@: as) -> (forall (cs :: LoT (S -> Type)). RenamingsK as cs -> (Name :@@: cs) -> r) -> r Source #

RelMonad Name Expr Source #

Expr is a monad relative to Name.

Instance details

Defined in Control.Monad.Foil.Example

Methods

rreturn :: forall (a :: S). Name a -> Expr a Source #

rbind :: forall (b :: S) (a :: S). Distinct b => Scope b -> Expr a -> (Name a -> Expr b) -> Expr b Source #

(Bifunctor sig, CoSinkable binder, SinkableK binder) => RelMonad Name (AST binder sig) Source #

AST sig is a monad relative to Name.

Instance details

Defined in Control.Monad.Free.Foil

Methods

rreturn :: forall (a :: S). Name a -> AST binder sig a Source #

rbind :: forall (b :: S) (a :: S). Distinct b => Scope b -> AST binder sig a -> (Name a -> AST binder sig b) -> AST binder sig b Source #

Binary (Name n) Source #

The raw id and nothing else. See the module documentation for what decoding trusts.

Instance details

Defined in Control.Monad.Free.Foil.Binary

Methods

put :: Name n -> Put #

get :: Get (Name n) #

putList :: [Name n] -> Put #

NFData (Name n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

rnf :: Name n -> () #

Show (Name n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

showsPrec :: Int -> Name n -> ShowS #

show :: Name n -> String #

showList :: [Name n] -> ShowS #

Eq (Name n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

(==) :: Name n -> Name n -> Bool #

(/=) :: Name n -> Name n -> Bool #

Ord (Name n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

compare :: Name n -> Name n -> Ordering #

(<) :: Name n -> Name n -> Bool #

(<=) :: Name n -> Name n -> Bool #

(>) :: Name n -> Name n -> Bool #

(>=) :: Name n -> Name n -> Bool #

max :: Name n -> Name n -> Name n #

min :: Name n -> Name n -> Name n #

nameId :: forall (l :: S). Name l -> Id Source #

Convert Name into an identifier. This may be useful for printing and debugging.

Since: 0.0.1

newtype NameBinder (n :: S) (l :: S) Source #

A name binder is a name that extends scope n to a (larger) scope l.

Since: 0.0.1

Constructors

UnsafeNameBinder (Name l) 

Instances

Instances details
CoSinkable NameBinder Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> NameBinder n l -> (forall (l' :: S). (Name l -> Name l') -> NameBinder n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> NameBinder n l -> (forall (o' :: S). DExt o o' => f n l o o' -> NameBinder o o' -> Scope o' -> r) -> r Source #

HasNameBinders NameBinder Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

getNameBinders :: forall (n :: S) (l :: S). NameBinder n l -> NameBinders n l Source #

unsafeSetNameBinders :: forall (n :: S) (l :: S) (l' :: S). NameBinder n l -> NameBinders n l' -> NameBinder n l' Source #

getNameBindersRaw :: forall (n :: S) (l :: S). NameBinder n l -> [RawName] Source #

reallyUnsafeSetNameBindersRaw :: forall (n :: S) (l :: S) (l' :: S). NameBinder n l -> [RawName] -> (NameBinder n l', [RawName]) Source #

UnifiablePattern NameBinder Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => NameBinder n l -> NameBinder n r -> UnifyNameBinders NameBinder n l r Source #

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> NameBinder n l -> NameBinder n r -> UnifyNameBinders NameBinder n l r Source #

Show (Expr n) Source #

Use ppExpr to show \(\lambda\)-terms.

Instance details

Defined in Control.Monad.Free.Foil.Example

Methods

showsPrec :: Int -> Expr n -> ShowS #

show :: Expr n -> String #

showList :: [Expr n] -> ShowS #

Binary (NameBinder n l) Source #

See the Binary instance of Name.

Instance details

Defined in Control.Monad.Free.Foil.Binary

Methods

put :: NameBinder n l -> Put #

get :: Get (NameBinder n l) #

putList :: [NameBinder n l] -> Put #

NFData (NameBinder n l) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

rnf :: NameBinder n l -> () #

Show (NameBinder n l) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

showsPrec :: Int -> NameBinder n l -> ShowS #

show :: NameBinder n l -> String #

showList :: [NameBinder n l] -> ShowS #

Eq (NameBinder n l) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

(==) :: NameBinder n l -> NameBinder n l -> Bool #

(/=) :: NameBinder n l -> NameBinder n l -> Bool #

Ord (NameBinder n l) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

compare :: NameBinder n l -> NameBinder n l -> Ordering #

(<) :: NameBinder n l -> NameBinder n l -> Bool #

(<=) :: NameBinder n l -> NameBinder n l -> Bool #

(>) :: NameBinder n l -> NameBinder n l -> Bool #

(>=) :: NameBinder n l -> NameBinder n l -> Bool #

max :: NameBinder n l -> NameBinder n l -> NameBinder n l #

min :: NameBinder n l -> NameBinder n l -> NameBinder n l #

SinkableK NameBinder Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (NameBinder :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (NameBinder :@@: cs) -> r) -> r Source #

emptyScope :: Scope 'VoidS Source #

An empty scope (without any names).

Since: 0.0.1

member :: forall (l :: S) (n :: S). Name l -> Scope n -> Bool Source #

A runtime check for potential name capture.

Since: 0.0.1

Extending scopes

extendScope :: forall (n :: S) (l :: S). NameBinder n l -> Scope n -> Scope l Source #

\(O(\min(n,W))\). Extend a scope with one name (safely). Note that as long as the foil is used as intended, the name binder is guaranteed to introduce a name that does not appear in the initial scope.

Since: 0.0.1

extendScopePattern :: forall (n :: S) pattern (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> Scope n -> Scope l Source #

Extend scope with variables inside a pattern. This is a more flexible version of extendScope.

Since: 0.0.1

newtype ExtendScope (n :: S) (l :: S) (o :: S) (o' :: S) Source #

Auxiliary data structure for scope extension. Used in extendScopePattern.

Since: 0.1.0

Constructors

ExtendScope (Scope n -> Scope l) 

idExtendScope :: forall (n :: S) (o :: S) (o' :: S). ExtendScope n n o o' Source #

Identity scope extension (no extension).

Since: 0.1.0

compExtendScope :: forall (n :: S) (i :: S) (o :: S) (o' :: S) (l :: S) (o'' :: S). ExtendScope n i o o' -> ExtendScope i l o' o'' -> ExtendScope n l o o'' Source #

Compose scope extensions.

Since: 0.1.0

Collecting new names

nameOf :: forall (n :: S) (l :: S). NameBinder n l -> Name l Source #

Extract name from a name binder.

Since: 0.0.1

namesOfPattern :: forall pattern (n :: S) (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> [Name l] Source #

Extract names from a pattern. This is a more flexible version of nameOf.

Since: 0.1.0

newtype NamesOf (n :: S) (l :: S) (o :: S) (o' :: S) Source #

Auxiliary structure collecting names in scope l that extend scope n. Used in namesOfPattern.

Since: 0.1.0

Constructors

NamesOf [Name l] 

idNamesOf :: forall (n :: S) (o :: S) (o' :: S). NamesOf n n o o' Source #

Empty list of names in scope n.

Since: 0.1.0

compNamesOf :: forall (n :: S) (i :: S) (o :: S) (o' :: S) (l :: S) (o'' :: S). NamesOf n i o o' -> NamesOf i l o' o'' -> NamesOf n l o o'' Source #

Concatenation of names, resulting in a list of names in l that extend scope n.

Since: 0.1.0

Refreshing binders

withFreshBinder :: forall (n :: S) r. Scope n -> (forall (l :: S). NameBinder n l -> r) -> r Source #

Allocate a fresh binder for a given scope.

Since: 0.0.1

withFresh :: forall (n :: S) r. Distinct n => Scope n -> (forall (l :: S). DExt n l => NameBinder n l -> r) -> r Source #

Safely produce a fresh name binder with respect to a given scope.

Since: 0.0.1

withFreshIn Source #

Arguments

:: forall (n :: S) r. Distinct n 
=> NameRange

The reservation to allocate from.

-> Scope n

The ambient scope.

-> (forall (l :: S). DExt n l => NameBinder n l -> r) 
-> r 

Safely produce a fresh name binder, allocated within a given range.

The binder is fresh with respect to the whole ambient scope, not merely to its part inside the range. Indeed, the allocated name lies in the range and is greater than every scope member there, while a scope member outside the range cannot be equal to a name inside it (see rawFreshNameIn). Thus the usual freshness evidence applies, and no invariant beyond the scope itself is required.

This is the primitive behind allocation policies such as per-module name blocks: reserve disjoint ranges for independently checked units, and the names allocated for them can never collide.

Fails with error when the range is exhausted. Use tryWithFreshIn to handle exhaustion instead.

>>> withFreshIn (NameRange 100 199) emptyScope (nameId . nameOf)
100

Since: 0.4.0

tryWithFreshIn Source #

Arguments

:: forall (n :: S) r. Distinct n 
=> NameRange

The reservation to allocate from.

-> Scope n

The ambient scope.

-> (forall (l :: S). DExt n l => NameBinder n l -> r) 
-> Maybe r 

A version of withFreshIn that reports an exhausted range with Nothing instead of failing. A driver that hands out ranges can then report which unit ran out of its reservation.

Since: 0.4.0

withFreshPattern Source #

Arguments

:: forall (o :: S) pattern (e :: S -> Type) (n :: S) (l :: S) r. (Distinct o, CoSinkable pattern, Sinkable e, InjectName e) 
=> Scope o

Ambient scope.

-> pattern n l

Pattern to refresh (if it clashes with the ambient scope).

-> (forall (o' :: S). DExt o o' => (Substitution e n o -> Substitution e l o') -> pattern o o' -> Scope o' -> r)

Continuation, accepting the refreshed pattern and the extended scope.

-> r 

Rename a given pattern into a fresh version of it to extend a given scope.

This is similar to withRefreshedPattern, except here renaming always takes place.

Since: 0.1.0

withRefreshed Source #

Arguments

:: forall (o :: S) (i :: S) r. Distinct o 
=> Scope o

Ambient scope.

-> Name i

Name to refresh (if it clashes with the ambient scope).

-> (forall (o' :: S). DExt o o' => NameBinder o o' -> r)

Continuation, accepting the refreshed name.

-> r 

Safely rename (if necessary) a given name to extend a given scope. This is similar to withFresh, except if the name does not clash with the scope, it can be used immediately, without renaming.

Since: 0.0.1

withRefreshedIn Source #

Arguments

:: forall (o :: S) (i :: S) r. Distinct o 
=> NameRange

The reservation to allocate a replacement from.

-> Scope o

Ambient scope.

-> Name i

Name to refresh (if it clashes with the ambient scope).

-> (forall (o' :: S). DExt o o' => NameBinder o o' -> r)

Continuation, accepting the refreshed name.

-> r 

A version of withRefreshed that allocates the replacement name within a given range when the candidate is taken. A client that reserves regions of the raw-name line (per-module stripes, a region for locals) uses this so that a rename cannot stray into someone else's reservation.

Since: 0.4.0

withRefreshedPattern Source #

Arguments

:: forall (o :: S) pattern (e :: S -> Type) (n :: S) (l :: S) r. (Distinct o, CoSinkable pattern, Sinkable e, InjectName e) 
=> Scope o

Ambient scope.

-> pattern n l

Pattern to refresh (if it clashes with the ambient scope).

-> (forall (o' :: S). DExt o o' => (Substitution e n o -> Substitution e l o') -> pattern o o' -> Scope o' -> r)

Continuation, accepting the refreshed pattern and the extended scope.

-> r 

Safely rename (if necessary) a given pattern to extend a given scope. This is similar to withFreshPattern, except if a name in the pattern does not clash with the scope, it can be used immediately, without renaming.

This is a more general version of withRefreshed.

The continuation also receives the scope extended with the refreshed pattern: the traversal computes it along the way, so the caller does not recompute it with extendScopePattern (a second traversal of the same pattern). The same holds for withFreshPattern and withRefreshedPattern'.

Note that there is deliberately no fast path for the case when every binder of the pattern is already fresh in the ambient scope. It is tempting to test all binders at once and, when none clashes, hand the continuation sink instead of a renaming composed per binder. That would be unsound.

Even when a binder is not renamed, the per-binder step is not the identity: addRename deletes the name from the substitution, which is how the binder shadows an outer binding of the same raw name. For skipping that delete to be harmless we would need the substitution's domain to avoid the pattern's binder names, but the substitution's domain lives in the pattern's own scope n, while freshness is tested against the unrelated ambient scope o.

The two can indeed disagree, because sink is a coercion and does not rename: a term built in a small scope keeps its binder names when it is placed in a larger one, so a binder can share a raw name with its own enclosing scope. Ordinary evaluation produces such terms, with a λ x1 nested inside another λ x1. Handing such a caller sink would apply its substitution to a name the pattern binds, which is to say capture the bound variable.

Since: 0.0.1

withRefreshedPattern' :: forall pattern (o :: S) e (n :: S) (l :: S) r. (CoSinkable pattern, Distinct o, InjectName e, Sinkable e) => Scope o -> pattern n l -> (forall (o' :: S). DExt o o' => ((Name n -> e o) -> Name l -> e o') -> pattern o o' -> Scope o' -> r) -> r Source #

Refresh (if needed) bound variables introduced in a pattern.

This is a version of withRefreshedPattern that uses functional renamings instead of Substitution.

Like withRefreshedPattern, this has no all-binders-already-fresh fast path, and for the same reason. Here shadowing is handled by unsinkName rather than by a delete: a name the pattern binds is routed to injectName and never reaches the caller's renaming, whether or not the binder was refreshed.

Since: 0.1.0

unsafeAssertFresh :: forall (n :: S) (l :: S) (n' :: S) (l' :: S) r. NameBinder n l -> (DExt n' l' => NameBinder n' l' -> r) -> r Source #

Unsafely declare that a given name (binder) is already fresh in any scope n'.

Since: 0.0.1

newtype WithRefreshedPattern (e :: S -> Type) (n :: S) (l :: S) (o :: S) (o' :: S) Source #

Auxiliary structure to accumulate substitution extensions produced when refreshing a pattern. Used in withRefreshedPattern and withFreshPattern.

Since: 0.1.0

Constructors

WithRefreshedPattern (Substitution e n o -> Substitution e l o') 

idWithRefreshedPattern :: forall (e :: S -> Type) (o :: S) (o' :: S) (n :: S). (Sinkable e, DExt o o') => WithRefreshedPattern e n n o o' Source #

Trivial substitution (coercion via sink).

Since: 0.1.0

compWithRefreshedPattern :: forall (o :: S) (o' :: S) (o'' :: S) (e :: S -> Type) (n :: S) (i :: S) (l :: S). (DExt o o', DExt o' o'') => WithRefreshedPattern e n i o o' -> WithRefreshedPattern e i l o' o'' -> WithRefreshedPattern e n l o o'' Source #

Composition of substitution extensions.

Since: 0.1.0

newtype WithRefreshedPattern' (e :: S -> Type) (n :: S) (l :: S) (o :: S) (o' :: S) Source #

Auxiliary structure to accumulate substitution extensions and the extended scope produced when refreshing a pattern. Similar to WithRefreshedPattern, except here substitutions are represented as functions. Used in withRefreshedPattern'.

Since: 0.1.0

Constructors

WithRefreshedPattern' ((Name n -> e o) -> Name l -> e o') 

idWithRefreshedPattern' :: forall (e :: S -> Type) (o :: S) (o' :: S) (n :: S). (Sinkable e, DExt o o') => WithRefreshedPattern' e n n o o' Source #

Trivial substitution extension (coercion via sink).

Since: 0.1.0

compWithRefreshedPattern' :: forall (o :: S) (o' :: S) (o'' :: S) (e :: S -> Type) (n :: S) (i :: S) (l :: S). (DExt o o', DExt o' o'') => WithRefreshedPattern' e n i o o' -> WithRefreshedPattern' e i l o' o'' -> WithRefreshedPattern' e n l o o'' Source #

Composition of substitution extensions.

Since: 0.1.0

Extracting proofs from binders and patterns

data DistinctEvidence (n :: S) where Source #

Evidence that scope n contains distinct names.

Since: 0.0.1

Constructors

Distinct :: forall (n :: S). Distinct n => DistinctEvidence n 

data ExtEvidence (n :: S) (l :: S) where Source #

Evidence that scope l extends scope n.

Since: 0.0.1

Constructors

Ext :: forall (n :: S) (l :: S). Ext n l => ExtEvidence n l 

assertDistinct :: forall (n :: S) pattern (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> DistinctEvidence l Source #

A distinct scope extended with a NameBinder is also distinct.

Since: 0.0.1

assertExt :: forall pattern (n :: S) (l :: S). CoSinkable pattern => pattern n l -> ExtEvidence n l Source #

A distinct scope extended with a NameBinder is also distinct.

Since: 0.0.3

unsafeDistinct :: forall (n :: S). DistinctEvidence n Source #

Unsafely declare that scope n is distinct. Used in unsafeAssertFresh.

Since: 0.0.1

unsafeExt :: forall (n :: S) (l :: S). ExtEvidence n l Source #

Unsafely declare that scope l extends scope n. Used in unsafeAssertFresh.

Since: 0.0.1

Unsinking names

unsinkName :: forall (n :: S) (l :: S). NameBinder n l -> Name l -> Maybe (Name n) Source #

Try coercing the name back to the (smaller) scope, given a binder that extends that scope.

Since: 0.0.1

unsinkNamePattern :: forall pattern (n :: S) (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> Name l -> Maybe (Name n) Source #

Check if a name in the extended context is introduced in a pattern or comes from the outer scope n.

This is a generalization of unsinkName.

Since: 0.1.0

newtype UnsinkName (n :: S) (l :: S) (o :: S) (o' :: S) Source #

Auxiliary structure for unsinking names. Used in unsinkNamePattern.

Since: 0.1.0

Constructors

UnsinkName (Name l -> Maybe (Name n)) 

idUnsinkName :: forall (n :: S) (o :: S) (o' :: S). UnsinkName n n o o' Source #

Trivial unsinking. If no scope extension took place, any name is free (since it cannot be bound by anything).

Since: 0.1.0

compUnsinkName :: forall (n :: S) (i :: S) (o :: S) (o' :: S) (l :: S) (o'' :: S). UnsinkName n i o o' -> UnsinkName i l o' o'' -> UnsinkName n l o o'' Source #

Composition of unsinking for nested binders/patterns.

Since: 0.1.0

Sets of names, and scope restriction

newtype NameSet (n :: S) Source #

A set of names of scope n.

This is not a Scope: a Scope is all the names in scope, and the foil relies on that (it is what freshness is tested against, and what Distinct speaks about). A NameSet is any subset of them, such as the names a term uses or the assumptions a declaration depends on, and carries no such invariant.

<> is union and mempty is empty, so a NameSet can be accumulated with foldMap.

Since: 0.4.0

Constructors

UnsafeNameSet RawScope 

Instances

Instances details
Sinkable NameSet Source #

A set of names sinks like anything else: rename each of its names.

As always, the proof is what makes sink a coercion here, and a coercion is what it has to be for a support computed under a binder to be usable in the scope outside it without rebuilding the set.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> NameSet n -> NameSet l Source #

NFData (NameSet n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

rnf :: NameSet n -> () #

Monoid (NameSet n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

mempty :: NameSet n #

mappend :: NameSet n -> NameSet n -> NameSet n #

mconcat :: [NameSet n] -> NameSet n #

Semigroup (NameSet n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

(<>) :: NameSet n -> NameSet n -> NameSet n #

sconcat :: NonEmpty (NameSet n) -> NameSet n #

stimes :: Integral b => b -> NameSet n -> NameSet n #

Eq (NameSet n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

(==) :: NameSet n -> NameSet n -> Bool #

(/=) :: NameSet n -> NameSet n -> Bool #

emptyNameSet :: forall (n :: S). NameSet n Source #

An empty set of names.

Since: 0.4.0

nameSetSingleton :: forall (n :: S). Name n -> NameSet n Source #

\(O(1)\). A set of one name.

Since: 0.4.0

nameSetInsert :: forall (n :: S). Name n -> NameSet n -> NameSet n Source #

\(O(\min(n,W))\). Add a name to a set.

Since: 0.4.0

nameSetMember :: forall (n :: S). Name n -> NameSet n -> Bool Source #

\(O(\min(n,W))\). Is this name in the set?

Since: 0.4.0

nameSetNull :: forall (n :: S). NameSet n -> Bool Source #

Is the set empty?

Since: 0.4.0

nameSetSize :: forall (n :: S). NameSet n -> Int Source #

How many names are in the set?

Since: 0.4.0

nameSetToList :: forall (n :: S). NameSet n -> [Name n] Source #

The names in the set, in ascending order of their identifiers.

Since: 0.4.0

nameSetFromList :: forall (n :: S). [Name n] -> NameSet n Source #

A set of the given names.

Since: 0.4.0

scopeToNameSet :: forall (n :: S). Scope n -> NameSet n Source #

All the names in a scope.

Since: 0.4.0

nameSetOfPattern :: forall binder (n :: S) (l :: S). CoSinkable binder => binder n l -> NameSet l Source #

The names a pattern binds.

Since: 0.4.0

nameSetSubsetOfScope :: forall (l :: S) (n :: S). NameSet l -> Scope n -> Bool Source #

\(O(\min(n,W))\). Does the scope contain every name in the set?

This is the test that restriction of a term comes down to, so it is the one place a restriction is paid for: compare a term's support against the scope it is to be restricted to.

Since: 0.4.0

unsinkNameSet :: forall binder (n :: S) (l :: S). CoSinkable binder => binder n l -> NameSet l -> NameSet n Source #

Drop the names a pattern binds, taking a set of names of the inner scope to a set of names of the outer one.

This is unsinkNamePattern for a whole set at once, and \(O(\min(n,W))\) rather than one membership test per name. Removing the pattern's names is right even when one of them shares a raw name with the enclosing scope: inside the pattern that raw name denotes the binder, so no occurrence of it there is an occurrence of the outer name.

Since: 0.4.0

withRestrictedScope Source #

Arguments

:: forall (n :: S) r. Distinct n 
=> NameSet n

Names to keep. Must be names of n.

-> (forall (m :: S). (Ext m n, Distinct m) => Scope m -> r) 
-> r 

Cut a scope down to a subset of its names.

The names must be names of n; nothing checks it, which is why this is the only entry point and takes a NameSet rather than a bare IntSet. The continuation gets Ext m n, so anything living in the smaller scope can be sinked back into the larger one for free, and Distinct m, since a subset of distinct names is distinct.

Note on allocation. A name allocated from the restricted scope is fresh with respect to m and not to n, so it may collide with a name of n that the restriction dropped. This is sound, since Ext m n gives no way to move a term of n into a scope extending m. It does mean that a restricted scope is for inspecting and restricting terms, and not a base to build new binders on and then mix with the original scope.

Since: 0.4.0

unsafeAssertRestricted :: forall (n :: S) (m :: S) r. Scope m -> ((Ext m n, Distinct m) => Scope m -> r) -> r Source #

Unsafely declare that a scope is a restriction of scope n. Used in withRestrictedScope.

Since: 0.4.0

Unification of binders

data UnifyNameBinders (pattern :: S -> S -> Type) (n :: S) (l :: S) (r :: S) where Source #

Unification result for two binders, extending some common scope to scopes l and r respectively.

Due to the implementation of the foil, we can often rename binders efficiently, by renaming binders only in one of the two unified terms.

Since: 0.0.3

Constructors

SameNameBinders

Binders are the same, proving that type parameters l and r are in fact equivalent.

Fields

  • :: forall (n :: S) (l :: S) (pattern :: S -> S -> Type). NameBinders n l

    Unordered set of binders in the unified pattern (from any of the original patterns).

  • -> UnifyNameBinders pattern n l l
     
RenameLeftNameBinder

It is possible to safely rename the left binder to match the right one.

Fields

RenameRightNameBinder

It is possible to safely rename the right binder to match the left one.

Fields

RenameBothBinders

It is necessary to rename both binders.

Fields

NotUnifiable :: forall (pattern :: S -> S -> Type) (n :: S) (l :: S) (r :: S). UnifyNameBinders pattern n l r

Cannot unify to (sub)patterns.

unifyNameBinders Source #

Arguments

:: forall (i :: S) (l :: S) (r :: S) (pattern :: S -> S -> Type). Distinct i 
=> NameBinder i l

Left pattern.

-> NameBinder i r

Right pattern.

-> UnifyNameBinders pattern i l r 

Unify binders either by asserting that they are the same, or by providing a safe renaming function to convert one binder to another.

When the binders differ, the one with the larger name is renamed towards the one with the smaller name. The direction is deliberate, but it is not what makes the renaming safe.

The renaming returned here is not applied by substituting names blindly. Callers push it through a term with liftRM, which refreshes a binder whenever it would capture. So the target name may well be used by a binder inside the term being renamed, and the result is still correct. Binder names do not always grow with depth: a term built in a small scope keeps its small binder names when sink places it in a larger one.

Since: 0.0.3

unsafeMergeUnifyBinders :: forall (pattern :: S -> S -> Type) (a :: S) (a' :: S) (a'' :: S) (a''' :: S) (b' :: S) (b'' :: S). UnifyNameBinders pattern a a' a'' -> UnifyNameBinders pattern a''' b' b'' -> UnifyNameBinders pattern a b' b'' Source #

Unsafely merge results of unification for nested binders/patterns. Used in andThenUnifyPatterns.

Since: 0.1.0

andThenUnifyPatterns Source #

Arguments

:: forall pattern (l :: S) (l' :: S) (n :: S) (r :: S) (r' :: S). (UnifiablePattern pattern, Distinct l, Distinct l') 
=> UnifyNameBinders pattern n l l'

Unifying action for some outer patterns.

-> (pattern l r, pattern l' r')

Two nested patterns (cannot be unified directly since they extend different scopes).

-> UnifyNameBinders pattern n r r' 

Chain unification of nested patterns.

Since: 0.1.0

andThenUnifyNameBinders Source #

Arguments

:: forall (pattern :: S -> S -> Type) (l :: S) (l' :: S) (n :: S) (r :: S) (r' :: S). (UnifiablePattern pattern, Distinct l, Distinct l') 
=> UnifyNameBinders pattern n l l'

Unifying action for some outer patterns.

-> (NameBinder l r, NameBinder l' r')

Two nested binders (cannot be unified directly since they extend different scopes).

-> UnifyNameBinders pattern n r r' 

Chain unification of nested patterns with NameBinders.

Since: 0.1.0

newtype NameBinders (n :: S) (l :: S) Source #

An unordered collection of NameBinders, that together extend scope n to scope l.

For an ordered version see NameBinderList.

Since: 0.1.0

Instances

Instances details
CoSinkable NameBinders Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> NameBinders n l -> (forall (l' :: S). (Name l -> Name l') -> NameBinders n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> NameBinders n l -> (forall (o' :: S). DExt o o' => f n l o o' -> NameBinders o o' -> Scope o' -> r) -> r Source #

SinkableK NameBinders Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (NameBinders :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (NameBinders :@@: cs) -> r) -> r Source #

unsafeMergeNameBinders :: forall (a :: S) (b :: S) (c :: S) (d :: S) (n :: S) (l :: S). NameBinders a b -> NameBinders c d -> NameBinders n l Source #

Unsafely merge sets of binders (via set union).

Since: 0.1.0

emptyNameBinders :: forall (n :: S). NameBinders n n Source #

An empty set of binders keeps the scope as is.

Since: 0.1.0

mergeNameBinders :: forall (n :: S) (i :: S) (l :: S). NameBinders n i -> NameBinders i l -> NameBinders n l Source #

Composition of sets of binders.

Since: 0.1.0

nameBindersSingleton :: forall (n :: S) (l :: S). NameBinder n l -> NameBinders n l Source #

A singleton name binder set.

Since: 0.1.0

data NameBinderList (n :: S) (l :: S) where Source #

An ordered collection (list) of NameBinders, that together extend scope n to scope l.

For an unordered version see NameBinders.

Since: 0.1.0

Constructors

NameBinderListEmpty :: forall (n :: S). NameBinderList n n

An empty list of binders keeps the scope as is.

NameBinderListCons

A non-empty list of binders.

Fields

Instances

Instances details
CoSinkable NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> NameBinderList n l -> (forall (l' :: S). (Name l -> Name l') -> NameBinderList n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> NameBinderList n l -> (forall (o' :: S). DExt o o' => f n l o o' -> NameBinderList o o' -> Scope o' -> r) -> r Source #

HasNameBinders NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

getNameBinders :: forall (n :: S) (l :: S). NameBinderList n l -> NameBinders n l Source #

unsafeSetNameBinders :: forall (n :: S) (l :: S) (l' :: S). NameBinderList n l -> NameBinders n l' -> NameBinderList n l' Source #

getNameBindersRaw :: forall (n :: S) (l :: S). NameBinderList n l -> [RawName] Source #

reallyUnsafeSetNameBindersRaw :: forall (n :: S) (l :: S) (l' :: S). NameBinderList n l -> [RawName] -> (NameBinderList n l', [RawName]) Source #

UnifiablePattern NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => NameBinderList n l -> NameBinderList n r -> UnifyNameBinders NameBinderList n l r Source #

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> NameBinderList n l -> NameBinderList n r -> UnifyNameBinders NameBinderList n l r Source #

SinkableK NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (NameBinderList :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (NameBinderList :@@: cs) -> r) -> r Source #

GenericK NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Associated Types

type RepK NameBinderList 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK NameBinderList = (((Var0 :: Atom (S -> S -> Type) S) :~~: (Var1 :: Atom (S -> S -> Type) S)) :=>: (U1 :: LoT (S -> S -> Type) -> Type)) :+: Exists S (Field ((NameBinder :$: (Var1 :: Atom (S -> S -> S -> Type) S)) ':@: (Var0 :: Atom (S -> S -> S -> Type) S)) :*: Field ((NameBinderList :$: (Var0 :: Atom (S -> S -> S -> Type) S)) ':@: (Var2 :: Atom (S -> S -> S -> Type) S)))

Methods

fromK :: forall (x :: LoT (S -> S -> Type)). (NameBinderList :@@: x) -> RepK NameBinderList x #

toK :: forall (x :: LoT (S -> S -> Type)). RepK NameBinderList x -> NameBinderList :@@: x #

type RepK NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK NameBinderList = (((Var0 :: Atom (S -> S -> Type) S) :~~: (Var1 :: Atom (S -> S -> Type) S)) :=>: (U1 :: LoT (S -> S -> Type) -> Type)) :+: Exists S (Field ((NameBinder :$: (Var1 :: Atom (S -> S -> S -> Type) S)) ':@: (Var0 :: Atom (S -> S -> S -> Type) S)) :*: Field ((NameBinderList :$: (Var0 :: Atom (S -> S -> S -> Type) S)) ':@: (Var2 :: Atom (S -> S -> S -> Type) S)))

nameBindersList :: forall (n :: S) (l :: S). NameBinders n l -> NameBinderList n l Source #

Convert an unordered set of name binders into an ordered list (with some order).

Since: 0.1.0

rawNameBinderList :: forall (n :: S) (l :: S). NameBinderList n l -> [RawName] Source #

The raw names a list of binders binds, outermost first.

Since: 0.4.0

withThinnedNameBinderList Source #

Arguments

:: forall (n :: S) (l :: S) r. Distinct n 
=> NameSet l

Names to keep, closed under whatever the binders carry.

-> NameBinderList n l

The chain to thin.

-> (forall (m :: S). (Ext n m, Ext m l, Distinct m) => NameBinderList n m -> r) 
-> r 

Keep only those binders of a list whose names are in a given set.

This is the thinning of a chain of binders, and it is what turns a support into a smaller chain in one step. The alternative, asking unsinkAST at every binder whether the term can do without it, walks the term once per binder, whereas a caller can compute the support once and thin against it.

The thinned scope m is produced rather than given, because there is nothing to give: a term's relevant scope (see withRelevantScope) is a subset of l and generally not an extension of n, since a term need not use everything already in scope. What comes back is n extended by the binders that survived, with Ext n m and Ext m l to place it between the two.

The set is taken as given. For a chain whose binders carry types, or anything else living in the intermediate scopes, the caller has to close the set under whatever those mention before thinning by it, since dropping a binder that a surviving binder's type refers to would leave that type unplaceable. The library cannot do that closure, having no view of what a binder carries.

Since: 0.4.0

unsafeAssertThinned :: forall (n :: S) (l :: S) (m :: S) r. NameBinderList n m -> ((Ext n m, Ext m l, Distinct m) => NameBinderList n m -> r) -> r Source #

Unsafely place a chain of binders between two scopes.

Sound for a chain thinned out of n to l: its names are those of n plus some of the binders between n and l, so it extends n, is extended by l, and is distinct because l was.

Since: 0.4.0

snocNameBinderList :: forall (n :: S) (i :: S) (l :: S). NameBinderList n i -> NameBinder i l -> NameBinderList n l Source #

Add a binder to the end of an (ordered) list of binders.

Note that NameBinderListCons adds a binder to the front of the list, which is the outermost position. This adds one to the innermost position instead.

Since: 0.3.1

concatNameBinderLists :: forall (n :: S) (i :: S) (l :: S). NameBinderList n i -> NameBinderList i l -> NameBinderList n l Source #

Concatenate two (ordered) lists of binders, the second extending the scope that the first extends to.

Since: 0.3.1

fromNameBindersList :: forall (n :: S) (l :: S). NameBinderList n l -> NameBinders n l Source #

Convert an ordered list of name binders into an unordered set.

Since: 0.1.0

Pattern combinators

data V2 (n :: S) (l :: S) Source #

An empty pattern type specifies zero possibilities for patterns.

This type can be used to specify that patterns are not possible.

Since: 0.1.0

Instances

Instances details
CoSinkable V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> V2 n l -> (forall (l' :: S). (Name l -> Name l') -> V2 n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> V2 n l -> (forall (o' :: S). DExt o o' => f n l o o' -> V2 o o' -> Scope o' -> r) -> r Source #

UnifiablePattern V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => V2 n l -> V2 n r -> UnifyNameBinders V2 n l r Source #

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> V2 n l -> V2 n r -> UnifyNameBinders V2 n l r Source #

SinkableK V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (V2 :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (V2 :@@: cs) -> r) -> r Source #

GenericK V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Associated Types

type RepK V2 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK V2 = V1 :: LoT (S -> S -> Type) -> Type

Methods

fromK :: forall (x :: LoT (S -> S -> Type)). (V2 :@@: x) -> RepK V2 x #

toK :: forall (x :: LoT (S -> S -> Type)). RepK V2 x -> V2 :@@: x #

type RepK V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK V2 = V1 :: LoT (S -> S -> Type) -> Type

absurd2 :: forall (n :: S) (l :: S) a. V2 n l -> a Source #

Since V2 values logically don't exist, this witnesses the logical reasoning tool of "ex falso quodlibet".

Since: 0.1.0

data U2 (n :: S) (l :: S) where Source #

A unit pattern type corresponds to a wildcard pattern.

Since: 0.1.0

Constructors

U2 

Fields

  • :: forall (n :: S). U2 n n

    Wildcard patten does not modify the scope.

Instances

Instances details
CoSinkable U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> U2 n l -> (forall (l' :: S). (Name l -> Name l') -> U2 n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> U2 n l -> (forall (o' :: S). DExt o o' => f n l o o' -> U2 o o' -> Scope o' -> r) -> r Source #

UnifiablePattern U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => U2 n l -> U2 n r -> UnifyNameBinders U2 n l r Source #

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> U2 n l -> U2 n r -> UnifyNameBinders U2 n l r Source #

SinkableK U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (U2 :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (U2 :@@: cs) -> r) -> r Source #

GenericK U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Associated Types

type RepK U2 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK U2 = ((Var0 :: Atom (S -> S -> Type) S) :~~: (Var1 :: Atom (S -> S -> Type) S)) :=>: (U1 :: LoT (S -> S -> Type) -> Type)

Methods

fromK :: forall (x :: LoT (S -> S -> Type)). (U2 :@@: x) -> RepK U2 x #

toK :: forall (x :: LoT (S -> S -> Type)). RepK U2 x -> U2 :@@: x #

type RepK U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

type RepK U2 = ((Var0 :: Atom (S -> S -> Type) S) :~~: (Var1 :: Atom (S -> S -> Type) S)) :=>: (U1 :: LoT (S -> S -> Type) -> Type)

Unifiable patterns

class CoSinkable pattern => UnifiablePattern (pattern :: S -> S -> Type) where Source #

A pattern type is unifiable if it is possible to match two patterns and decide how to rename binders.

Note that the default implementation compares patterns only up to their binders. See unifyPatterns for what that does and does not distinguish.

Since: 0.0.1

Minimal complete definition

Nothing

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => pattern n l -> pattern n r -> UnifyNameBinders pattern n l r Source #

Unify two patterns and decide which binders need to be renamed.

Since: 0.1.0

default unifyPatterns :: forall (n :: S) (l :: S) (r :: S). (CoSinkable pattern, Distinct n) => pattern n l -> pattern n r -> UnifyNameBinders pattern n l r Source #

The default implementation flattens both patterns to their binders (via nameBinderListOf) and unifies the resulting NameBinderLists. It therefore compares only the number and order of binders, and ignores

  • the constructor, so two patterns built from different constructors with the same number of binders unify;
  • non-binding fields (locations, sorts, literals), whatever their values;
  • the nesting of sub-patterns, so (x, (y, z)) unifies with ((x, y), z).

For most languages this is the intended notion of α-equivalence: what the body of a binding construct can refer to is precisely the pattern's binders, in order. Since α-equivalence is defined in terms of unifyPatterns, this also means that terms differing only in such a pattern are α-equivalent.

A pattern that carries semantically relevant data needs the instance written by hand instead. Use UnifiableInPattern to compare non-binding fields, which also lets an instance ignore some of them deliberately, as a generated instance does for BNFC source positions.

A field that is scope-indexed, such as a telescope step's type, cannot be compared here at all, since comparing it up to α needs the ambient scope and this method is given only Distinct. Write unifyPatternsIn for that, and leave this one as the binder-only approximation.

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> pattern n l -> pattern n r -> UnifyNameBinders pattern n l r Source #

Unify two patterns with the ambient scope at hand.

Everything in the library that compares patterns and holds a scope goes through this method, α-equivalence included, so this is the one to implement when the comparison needs a scope. Comparing the payloads of a pattern that carries them does: alphaEquivIn asks for a Scope.

Note that the verdict speaks about binders, so an instance comparing payloads has to apply the renaming the verdict prescribes before it compares them, exactly as alphaEquivScoped applies it to the body of a scoped term. Two telescopes (A : 𝕌) (x : A) and (B : 𝕌) (y : B) are α-equivalent, and their second payloads are only equal once the first binders have been identified.

The default ignores the scope and answers with unifyPatterns. An instance that overrides this one should leave unifyPatterns in place as the binder-only approximation rather than remove it. That is what unsafeEqPattern and any caller without a scope will get, and it may be more permissive than this one, never less.

Instances

Instances details
UnifiablePattern NameBinder Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => NameBinder n l -> NameBinder n r -> UnifyNameBinders NameBinder n l r Source #

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> NameBinder n l -> NameBinder n r -> UnifyNameBinders NameBinder n l r Source #

UnifiablePattern NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => NameBinderList n l -> NameBinderList n r -> UnifyNameBinders NameBinderList n l r Source #

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> NameBinderList n l -> NameBinderList n r -> UnifyNameBinders NameBinderList n l r Source #

UnifiablePattern U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => U2 n l -> U2 n r -> UnifyNameBinders U2 n l r Source #

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> U2 n l -> U2 n r -> UnifyNameBinders U2 n l r Source #

UnifiablePattern V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => V2 n l -> V2 n r -> UnifyNameBinders V2 n l r Source #

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> V2 n l -> V2 n r -> UnifyNameBinders V2 n l r Source #

(Sinkable e, AlphaEquiv e, RelMonad Name e) => UnifiablePattern (Telescope label e) Source #

Two telescopes unify when their binders line up and their payloads agree.

Labels are ignored, which is what α-equivalence should do with a label: a parameter's spelling is no more relevant than a bound variable's. Payloads are not, since two telescopes agreeing on binders may well disagree on types.

unifyPatterns is the binder-only approximation, which is all a caller without a scope can be given. unifyPatternsIn is the real answer, and it is what the library's α-equivalence calls.

Instance details

Defined in Control.Monad.Foil.Telescope

Methods

unifyPatterns :: forall (n :: S) (l :: S) (r :: S). Distinct n => Telescope label e n l -> Telescope label e n r -> UnifyNameBinders (Telescope label e) n l r Source #

unifyPatternsIn :: forall (n :: S) (l :: S) (r :: S). Distinct n => Scope n -> Telescope label e n l -> Telescope label e n r -> UnifyNameBinders (Telescope label e) n l r Source #

class AlphaEquiv (e :: S -> Type) where Source #

Comparison of scope-indexed values up to α, in a known scope.

unifyPatterns is given only Distinct, which is enough to line up binders and not enough to compare anything living in a scope. A pattern that carries a payload needs this to compare its payloads against another's, which is what unifyPatternsIn is for.

Since: 0.4.0

Methods

alphaEquivIn :: forall (n :: S). Distinct n => Scope n -> e n -> e n -> Bool Source #

Are two values of one scope α-equivalent?

Since: 0.4.0

Instances

Instances details
AlphaEquiv Name Source #

A name is α-equivalent only to itself.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

alphaEquivIn :: forall (n :: S). Distinct n => Scope n -> Name n -> Name n -> Bool Source #

(Bitraversable sig, ZipMatchK sig, UnifiablePattern binder, SinkableK binder) => AlphaEquiv (AST binder sig) Source #

A term is a scope-indexed value that can be compared up to α, which is what a pattern carrying terms as payloads needs of them.

Instance details

Defined in Control.Monad.Free.Foil

Methods

alphaEquivIn :: forall (n :: S). Distinct n => Scope n -> AST binder sig n -> AST binder sig n -> Bool Source #

class UnifiableInPattern a where Source #

Unification of values in patterns. By default, Eq instance is used, but it may be useful to ignore some data in pattens (such as location annotations).

Since: 0.1.0

Minimal complete definition

Nothing

Methods

unifyInPattern :: a -> a -> Bool Source #

Unify non-binding components of a pattern.

Since: 0.1.0

default unifyInPattern :: Eq a => a -> a -> Bool Source #

unsafeEqPattern :: forall pattern (n :: S) (l :: S) (n' :: S) (l' :: S). (UnifiablePattern pattern, Distinct n) => pattern n l -> pattern n' l' -> Bool Source #

The easiest way to compare two patterns is to check if they are the same. This function is labelled unsafe, since we generally are interested in proper α-equivalence instead of direct equality.

Since: 0.1.0

Safe sinking

class Sinkable (e :: S -> Type) where Source #

Sinking an expression from scope n into a (usualy extended) scope l, given the renaming (injection from scope n to scope l).

Since: 0.0.1

Minimal complete definition

Nothing

Methods

sinkabilityProof Source #

Arguments

:: forall (n :: S) (l :: S). (Name n -> Name l)

Map names from scope n to a (possibly larger) scope l.

-> e n

Expression with free variables in scope n.

-> e l 

An implementation of this method that typechecks proves to the compiler that the expression is indeed Sinkable. However, instead of this implementation, sink should be used at all call sites for efficiency.

default sinkabilityProof :: forall (n :: S) (l :: S). (GenericK e, GSinkableK (RepK e)) => (Name n -> Name l) -> e n -> e l Source #

Instances

Instances details
Sinkable Expr Source #

This instance serves as a proof that sinking of Expr is safe.

Instance details

Defined in Control.Monad.Foil.Example

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> Expr n -> Expr l Source #

Sinkable Name Source #

Sinking a Name is as simple as applying the renaming.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> Name n -> Name l Source #

Sinkable NameSet Source #

A set of names sinks like anything else: rename each of its names.

As always, the proof is what makes sink a coercion here, and a coercion is what it has to be for a support computed under a binder to be usable in the scope outside it without rebuilding the set.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> NameSet n -> NameSet l Source #

Sinkable e => Sinkable (Substitution e i) Source #

Substitutions are sinkable as long as corresponding expressions are.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> Substitution e i n -> Substitution e i l Source #

(Bifunctor sig, CoSinkable binder, SinkableK binder) => Sinkable (AST binder sig) Source # 
Instance details

Defined in Control.Monad.Free.Foil

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> AST binder sig n -> AST binder sig l Source #

(Bifunctor sig, CoSinkable binder, SinkableK binder) => Sinkable (ScopedAST binder sig) Source # 
Instance details

Defined in Control.Monad.Free.Foil

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> ScopedAST binder sig n -> ScopedAST binder sig l Source #

(Functor f, Sinkable e) => Sinkable (Compose f e) Source #

A container of sinkable expressions is sinkable, elementwise.

The point of this instance is sinkContainer: since the proof typechecks, sinking the whole container is a coercion, and does not walk its spine.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> Compose f e n -> Compose f e l Source #

sink :: forall e (n :: S) (l :: S). (Sinkable e, DExt n l) => e n -> e l Source #

Efficient version of sinkabilityProof. In fact, once sinkabilityProof typechecks, it is safe to sink by coercion. See Section 3.5 in «The Foil: Capture-Avoiding Substitution With No Sharp Edges» for the details.

sink is the base of a family of \(O(1)\) coercions, named after Data.Functor.Classes: sink1 sinks through one Functor layer and sink2 through a Bifunctor, each justified by a lifted sinkability proof of its own.

Tuples and records need no private unsafeCoerce helpers either. A pair of sinkables is a sink2 (Tannen for a whole container of them), and a pair whose first component is scope-free is a sink1 through Compose f ((,) a). A record of sinkable fields derives Sinkable through deriveGenericK and empty SinkableK and Sinkable instances, after which the whole record sinks in one coercion. A record holding the Scope itself is rightly refused, since there is no SinkableK Scope: the scope must grow when a binder is entered, so keep it beside the sinkable part and not inside it.

Do not map sink over a container. fmap sink walks the whole spine to apply a per-element coercion, where sink1 is one coercion. Rewrite rules turn the elementwise forms into the corresponding family member where they fire, but they are best-effort (they need optimisation on, and fmap at a known functor is often resolved to the instance method first), so write the family member directly.

Since: 0.0.1

sink1 :: forall f e (n :: S) (l :: S). (Functor f, Sinkable e, DExt n l) => f (e n) -> f (e l) Source #

Sink an entire container of sinkable expressions, in \(O(1)\): sink lifted through one Functor layer, justified by the Sinkable instance of Compose.

The soundness argument for sink extends to a container of sinkables, such as an IntMap of terms, a Map keyed by something else, or a list of them. So there is no need to walk the spine with fmap sink, and entering a binder need not be \(O(size)\).

>>> :{
sinkEnv :: DExt n l => Map.Map String (Name n) -> Map.Map String (Name l)
sinkEnv = sink1
:}

A nested container is one Compose away: f (g (e n)) is Compose f g (e n), and the composition is again a Functor, so sink1 covers it too.

Two things this does not cover:

  • A Scope is not sinkable, and must not be sunk: it is the set of names in scope n, and it has to grow when a binder is entered (see extendScope).
  • A NameMap must stay total on the names in scope (lookupName errors otherwise), so sinking one has to be paired with adding the new binder's entry (see addNameBinder).

Since: 0.4.0

sinkContainer :: forall f e (n :: S) (l :: S). (Functor f, Sinkable e, DExt n l) => f (e n) -> f (e l) Source #

Deprecated: Use sink1, its name in the sink family

The name sink1 had before the family existed.

Since: 0.3.2

sinkabilityProof2 Source #

Arguments

:: forall p e1 e2 (n :: S) (n' :: S) (m :: S) (m' :: S). (Bifunctor p, Sinkable e1, Sinkable e2) 
=> (Name n -> Name n')

Map names of scope n into scope n'.

-> (Name m -> Name m')

Map names of scope m into scope m'.

-> p (e1 n) (e2 m) 
-> p (e1 n') (e2 m') 

The sinkability proof lifted through a Bifunctor, with one renaming per slot. Once this typechecks, sinking both slots at once is a coercion; sink2 is to this proof exactly what sink is to sinkabilityProof.

Since: 0.4.0

sink2 :: forall p e1 e2 (n :: S) (n' :: S) (m :: S) (m' :: S). (Bifunctor p, Sinkable e1, Sinkable e2, DExt n n', DExt m m') => p (e1 n) (e2 m) -> p (e1 n') (e2 m') Source #

Sink both slots of a Bifunctor of sinkables, in \(O(1)\), the two scopes moving independently: the shape of liftEq2, with a coercion in place of each of the two functions.

>>> :{
sinkBoth :: (DExt n n', DExt m m') => (Name n, Name m) -> (Name n', Name m')
sinkBoth = sink2
:}

A container of such pairs is a Bifunctor again, via Tannen, so a list of pairs of names, the shape an α-equivalence test threads, also sinks in one coercion:

>>> :{
sinkPairs :: (DExt n n', DExt m m') => [(Name n, Name m)] -> [(Name n', Name m')]
sinkPairs = runTannen . sink2 . Tannen
:}

Since: 0.4.0

extendRenaming Source #

Arguments

:: forall pattern (n :: S) (n' :: S) (l :: S) r. CoSinkable pattern 
=> (Name n -> Name n')

Map names from scope n to a (possibly larger) scope n'.

-> pattern n l

A pattern that extends scope n to another scope l.

-> (forall (l' :: S). (Name l -> Name l') -> pattern n' l' -> r)

A continuation, accepting an extended renaming from l to l' (which itself extends n') and a (possibly refreshed) pattern that extends n' to l'.

-> r 

Extend renaming when going under a CoSinkable pattern (generalized binder). Note that the scope under pattern is independent of the codomain of the renaming.

This function is used to go under binders when implementing sinkabilityProof and is both a generalization of extendRenamingNameBinder and an efficient implementation of coSinkabilityProof.

Since: 0.0.1

extendNameBinderRenaming Source #

Arguments

:: forall pattern (i :: S) (n :: S) (n' :: S) (l :: S) r. CoSinkable pattern 
=> (NameBinder i n -> NameBinder i n')

Map names from scope n to a (possibly larger) scope n'.

-> pattern n l

A pattern that extends scope n to another scope l.

-> (forall (l' :: S). (NameBinder n' l -> NameBinder n' l') -> pattern n' l' -> r)

A continuation, accepting an extended renaming from l to l' (which itself extends n') and a (possibly refreshed) pattern that extends n' to l'.

-> r 

Extend renaming of binders when going under a CoSinkable pattern (generalized binder). Note that the scope under pattern is independent of the codomain of the renaming.

Since: 0.0.3

composeNameBinderRenamings Source #

Arguments

:: forall (n :: S) (i :: S) (i' :: S) (l :: S) (l' :: S). (NameBinder n i -> NameBinder n i')

Rename binders extending scope n from i to i'.

-> (NameBinder i' l -> NameBinder i' l')

Rename binders extending scope i' from l to l'.

-> NameBinder n l 
-> NameBinder n l' 

Safely compose renamings of name binders. The underlying implementation is

Since: 0.0.3

fromNameBinderRenaming :: forall (n :: S) (l :: S) (l' :: S). (NameBinder n l -> NameBinder n l') -> Name l -> Name l' Source #

Convert renaming of name binders into renaming of names in the inner scopes.

Since: 0.0.3

extendRenamingNameBinder Source #

Arguments

:: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n')

Map names from scope n to a (possibly larger) scope n'.

-> NameBinder n l

A name binder that extends scope n to another scope l.

-> (forall (l' :: S). (Name l -> Name l') -> NameBinder n' l' -> r)

A continuation, accepting an extended renaming from l to l' (which itself extends n') and a (possibly refreshed) binder that extends n' to l'.

-> r 

Extend renaming when going under a NameBinder. Note that the scope under binder is independent of the codomain of the renaming.

Semantically, this function may need to rename the binder (resulting in the new scope l'), to make sure it does not clash with scope n'. However, as it turns out, the foil makes it safe to implement this function as a coercion. See Appendix A in «The Foil: Capture-Avoiding Substitution With No Sharp Edges» for the details.

This function is used to go under binders when implementing sinkabilityProof. A generalization of this function is extendRenaming (which is an efficient version of coSinkabilityProof).

Since: 0.0.1

class CoSinkable (pattern :: S -> S -> Type) where Source #

CoSinkable is to patterns (generalized binders) what Sinkable is to expressions.

See Section 2.3 of «Free Foil: Generating Efficient and Scope-Safe Abstract Syntax» for more details.

Since: 0.0.1

Minimal complete definition

Nothing

Methods

coSinkabilityProof Source #

Arguments

:: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n')

Map names from scope n to a (possibly larger) scope n'.

-> pattern n l

A pattern that extends scope n to another scope l.

-> (forall (l' :: S). (Name l -> Name l') -> pattern n' l' -> r)

A continuation, accepting an extended renaming from l to l' (which itself extends n') and a (possibly refreshed) pattern that extends n' to l'.

-> r 

An implementation of this method that typechecks proves to the compiler that the pattern is indeed CoSinkable. However, instead of this implementation, extendRenaming should be used at all call sites for efficiency.

default coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (GenericK pattern, GSinkableK (RepK pattern)) => (Name n -> Name n') -> pattern n l -> (forall (l' :: S). (Name l -> Name l') -> pattern n' l' -> r) -> r Source #

withPattern Source #

Arguments

:: forall (o :: S) f (n :: S) (l :: S) r. Distinct o 
=> (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r')

Processing of a single NameBinder, this will be applied to each binder in a pattern.

-> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z')

Result in case no binders are present. This can be seen as scope-indexed mempty.

-> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'')

Composition of results for nested binders/patterns. This can be seen as scope-indexed mappend.

-> Scope o

Ambient scope.

-> pattern n l

Pattern to process.

-> (forall (o' :: S). DExt o o' => f n l o o' -> pattern o o' -> Scope o' -> r)

Continuation, accepting the result for the entire pattern, a (possibly refreshed) pattern, and the scope extended by that pattern.

-> r 

Generalized processing of a pattern.

You can see withPattern as a CPS-style traversal over the binders in a pattern.

Patterns that carry scoped payloads

Note that the ambient scope o and the pattern's own scope n are unrelated: nameBinderListOf passes emptyScope and namesOfPattern passes no scope at all. The only thing relating the two is the pair of binders each step of the traversal produces, the one the pattern has and the one the callback hands back.

A pattern whose fields are all binders and plain data does not notice this, and can take the default implementation. A pattern carrying a field indexed by its own scope, such as the type of a telescope's step, does notice: to rebuild that field at o it needs a renaming, and the only honest one is the identity on the raw names the pattern does not bind, corrected at the binders that were refreshed. That renaming is PatternTransport, and such a pattern should implement withPattern by hand, threading one through the traversal. See transportPayload for the whole recipe.

The default implementation cannot do this, since it goes through unsafeSetNameBinders, which replaces the binders and leaves every other field as it stands: a payload mentioning a refreshed binder would keep the name that binder used to have. Rather than answer wrongly, it refuses: a field indexed by a scope is a type error in the generic implementation, naming the field and pointing here.

default withPattern :: forall (o :: S) f (n :: S) (l :: S) r. (Distinct o, GenericK pattern, GValidNameBinders pattern (RepK pattern), GHasNameBinders (RepK pattern)) => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> pattern n l -> (forall (o' :: S). DExt o o' => f n l o o' -> pattern o o' -> Scope o' -> r) -> r Source #

Instances

Instances details
CoSinkable NameBinder Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> NameBinder n l -> (forall (l' :: S). (Name l -> Name l') -> NameBinder n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> NameBinder n l -> (forall (o' :: S). DExt o o' => f n l o o' -> NameBinder o o' -> Scope o' -> r) -> r Source #

CoSinkable NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> NameBinderList n l -> (forall (l' :: S). (Name l -> Name l') -> NameBinderList n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> NameBinderList n l -> (forall (o' :: S). DExt o o' => f n l o o' -> NameBinderList o o' -> Scope o' -> r) -> r Source #

CoSinkable NameBinders Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> NameBinders n l -> (forall (l' :: S). (Name l -> Name l') -> NameBinders n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> NameBinders n l -> (forall (o' :: S). DExt o o' => f n l o o' -> NameBinders o o' -> Scope o' -> r) -> r Source #

CoSinkable U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> U2 n l -> (forall (l' :: S). (Name l -> Name l') -> U2 n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> U2 n l -> (forall (o' :: S). DExt o o' => f n l o o' -> U2 o o' -> Scope o' -> r) -> r Source #

CoSinkable V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> V2 n l -> (forall (l' :: S). (Name l -> Name l') -> V2 n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> V2 n l -> (forall (o' :: S). DExt o o' => f n l o o' -> V2 o o' -> Scope o' -> r) -> r Source #

Sinkable e => CoSinkable (Telescope label e) Source #

A telescope is a pattern, so the foil's own machinery walks it.

coSinkabilityProof typechecks only because a payload is sunk by the renaming of the scope before its binder, rather than by the extended one.

withPattern has to be written out rather than derived. The generic implementation refuses a pattern with a field indexed by a scope, since it would leave a payload that names a refreshed binder pointing at the name that binder used to have. This instance follows the recipe in transportPayload: a PatternTransport threaded through the traversal, with each payload moved by the transport accumulated before its own binder, that being the scope the payload lives in.

Instance details

Defined in Control.Monad.Foil.Telescope

Methods

coSinkabilityProof :: forall (n :: S) (n' :: S) (l :: S) r. (Name n -> Name n') -> Telescope label e n l -> (forall (l' :: S). (Name l -> Name l') -> Telescope label e n' l' -> r) -> r Source #

withPattern :: forall (o :: S) f (n :: S) (l :: S) r. Distinct o => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> Telescope label e n l -> (forall (o' :: S). DExt o o' => f n l o o' -> Telescope label e o o' -> Scope o' -> r) -> r Source #

Transporting a pattern's payloads

data PatternTransport (n :: S) (o :: S) Source #

The renaming that carries a pattern's payloads into the ambient scope of withPattern.

A pattern may carry fields indexed by its own scope, the standard example being a telescope, where each step has a type in the scope the steps before it extend to. Rebuilding such a pattern at the ambient scope means rebuilding those fields there too, and withPattern hands the instance no renaming for it. This is that renaming, accumulated as the traversal goes.

It is abstract on purpose: the only ways to build one are verbatimTransport and transportUnderBinder, which together are exactly what a correct withPattern does.

Soundness rests on what withPattern is allowed to do. It replaces binders and nothing else, so a raw name the pattern does not bind means in o what it meant in n, and the identity on raw names is a renaming from the one to the other. That is the same coercion extendRenaming and unsafeAssertFresh already perform.

Since: 0.4.0

Constructors

TransportVerbatim

No binder was refreshed, so raw names are unchanged throughout.

TransportRenamed (Name n -> Name o)

Some binder was refreshed, so payloads have to be traversed.

verbatimTransport :: forall (n :: S) (o :: S). PatternTransport n o Source #

The transport to start a withPattern traversal with, before any binder has been seen.

Since: 0.4.0

transportUnderBinder Source #

Arguments

:: forall (n :: S) (o :: S) (i :: S) (o' :: S). PatternTransport n o 
-> NameBinder n i

The binder as the pattern has it.

-> NameBinder o o'

The binder withPattern handed back.

-> PatternTransport i o' 

Extend a transport by one binder of the pattern.

The names of the inner scope are the binder's own, which goes to whatever the refreshed binder introduces, and the names of the outer scope, which the transport so far already answers for.

Since: 0.4.0

transportPayload :: forall e (n :: S) (o :: S). Sinkable e => PatternTransport n o -> e n -> e o Source #

Carry a payload along a transport.

The Sinkable instance does the walking, and only when it has to. While no binder has been refreshed the payload is taken over as it stands, so the traversals that never rename (extendScopePattern, namesOfPattern, nameBinderListOf) do not walk payloads at all.

The whole recipe for a payload-carrying pattern, at a telescope of labelled steps:

instance Sinkable e => CoSinkable (Telescope label e) where
  withPattern withBinder unit comp = go verbatimTransport
    where
      go _transport _scope TelescopeEmpty cont = cont unit TelescopeEmpty
      go transport scope (TelescopeCons label payload binder rest) cont =
        withBinder scope binder $ \fbinder binder' ->
          go (transportUnderBinder transport binder binder')
             (extendScope binder' scope) rest $ \frest rest' ->
            cont (comp fbinder frest)
              (TelescopeCons label (transportPayload transport payload)
                             binder' rest')

Note which transport each payload takes: the one accumulated before its own binder, since that is the scope the payload lives in.

Since: 0.4.0

transportName :: forall (n :: S) (o :: S). PatternTransport n o -> Name n -> Name o Source #

Carry a single name along a transport.

Since: 0.4.0

newtype WithNameBinderList (r :: S) (n :: S) (l :: S) (o :: S) (o' :: S) Source #

Auxiliary data structure for collecting name binders. Used in nameBinderListOf.

Since: 0.2.0

idWithNameBinderList :: forall (o :: S) (o' :: S) (r :: S) (n :: S). DExt o o' => WithNameBinderList r n n o o' Source #

Empty list of name binders (identity).

Since: 0.2.0

compWithNameBinderList :: forall (o :: S) (o' :: S) (o'' :: S) (r :: S) (n :: S) (i :: S) (l :: S). (DExt o o', DExt o' o'') => WithNameBinderList r n i o o' -> WithNameBinderList r i l o' o'' -> WithNameBinderList r n l o o'' Source #

Concatenating lists of name binders (compose).

Since: 0.2.0

nameBinderListOf :: forall binder (n :: S) (l :: S). CoSinkable binder => binder n l -> NameBinderList n l Source #

Collect name binders of a generalized pattern into a name binder list, which can be more easily traversed.

Since: 0.2.0

Safe substitions

newtype Substitution (e :: S -> Type) (i :: S) (o :: S) Source #

A substitution is a mapping from names in scope i to expressions e o in scope o.

Since: 0.0.1

Constructors

UnsafeSubstitution (IntMap (e o)) 

Instances

Instances details
Sinkable e => Sinkable (Substitution e i) Source #

Substitutions are sinkable as long as corresponding expressions are.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProof :: forall (n :: S) (l :: S). (Name n -> Name l) -> Substitution e i n -> Substitution e i l Source #

lookupSubst :: forall e (i :: S) (o :: S). InjectName e => Substitution e i o -> Name i -> e o Source #

Apply substitution to a given name.

Since: 0.0.1

identitySubst :: forall (e :: S -> Type) (i :: S). InjectName e => Substitution e i i Source #

Identity substitution maps all names to expresion-variables.

Since: 0.0.1

nullSubst :: forall (e :: S -> Type) (i :: S) (o :: S). Substitution e i o -> Bool Source #

Whether a substitution maps every name to itself (see addRename, which deletes identity renames, so this is one null test).

Since: 0.4.0

voidSubst :: forall (e :: S -> Type) (n :: S). Substitution e 'VoidS n Source #

An empty substitution from an empty scope.

Since: 0.2.0

addSubst :: forall e (i :: S) (o :: S) (i' :: S). Substitution e i o -> NameBinder i i' -> e o -> Substitution e i' o Source #

Extend substitution with a particular mapping.

Since: 0.0.1

addSubstPattern :: forall binder e (i :: S) (o :: S) (i' :: S). CoSinkable binder => Substitution e i o -> binder i i' -> [e o] -> Substitution e i' o Source #

Extend a substitution with a value for each binder of a pattern, in the order the pattern binds them.

Since: 0.2.0

addSubstList :: forall e (i :: S) (o :: S) (i' :: S). Substitution e i o -> NameBinderList i i' -> [e o] -> Substitution e i' o Source #

Extend a substitution with a value for each binder of a chain, in order. Fails with error when the list of values is too short.

Since: 0.2.0

addRename :: forall (e :: S -> Type) (i :: S) (o :: S) (i' :: S). InjectName e => Substitution e i o -> NameBinder i i' -> Name o -> Substitution e i' o Source #

Add variable renaming to a substitution.

When the binder is mapped to its own name, the name is deleted from the substitution rather than mapped to itself. This is an optimization, but it is not only an optimization: it is also how the binder shadows an outer binding of the same raw name, so the delete cannot be skipped even when nothing is being renamed. See withRefreshedPattern for why that rules out an all-binders-fresh fast path.

Since: 0.0.1

Name maps

newtype NameMap (n :: S) a Source #

A total map from names in scope n to elements of type a.

Since: 0.0.1

Constructors

NameMap 

Fields

Instances

Instances details
Functor (NameMap n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

fmap :: (a -> b) -> NameMap n a -> NameMap n b #

(<$) :: a -> NameMap n b -> NameMap n a #

Foldable (NameMap n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

fold :: Monoid m => NameMap n m -> m #

foldMap :: Monoid m => (a -> m) -> NameMap n a -> m #

foldMap' :: Monoid m => (a -> m) -> NameMap n a -> m #

foldr :: (a -> b -> b) -> b -> NameMap n a -> b #

foldr' :: (a -> b -> b) -> b -> NameMap n a -> b #

foldl :: (b -> a -> b) -> b -> NameMap n a -> b #

foldl' :: (b -> a -> b) -> b -> NameMap n a -> b #

foldr1 :: (a -> a -> a) -> NameMap n a -> a #

foldl1 :: (a -> a -> a) -> NameMap n a -> a #

toList :: NameMap n a -> [a] #

null :: NameMap n a -> Bool #

length :: NameMap n a -> Int #

elem :: Eq a => a -> NameMap n a -> Bool #

maximum :: Ord a => NameMap n a -> a #

minimum :: Ord a => NameMap n a -> a #

sum :: Num a => NameMap n a -> a #

product :: Num a => NameMap n a -> a #

Traversable (NameMap n) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

traverse :: Applicative f => (a -> f b) -> NameMap n a -> f (NameMap n b) #

sequenceA :: Applicative f => NameMap n (f a) -> f (NameMap n a) #

mapM :: Monad m => (a -> m b) -> NameMap n a -> m (NameMap n b) #

sequence :: Monad m => NameMap n (m a) -> m (NameMap n a) #

emptyNameMap :: NameMap 'VoidS a Source #

An empty map belongs in the empty scope.

Since: 0.0.1

mapWithName :: forall (n :: S) a b. (Name n -> a -> b) -> NameMap n a -> NameMap n b Source #

Map over a NameMap, with the name each value belongs to.

This is the keyed version of the derived Functor instance. It cannot change which names the map is defined on, so a map that was total stays total, which is what makes it a safe way to build a Substitution out of one: see nameMapToSubstitution.

Since: 0.4.0

nameMapToSubstitution :: forall (i :: S) e (o :: S). NameMap i (e o) -> Substitution e i o Source #

Convert a NameMap of expressions into a Substitution.

Since: 0.2.0

nameMapToScope :: forall (n :: S) a. NameMap n a -> Scope n Source #

Convert a NameMap of expressions into a Scope.

Since: 0.3.0

addNameBinders :: forall binder (n :: S) (l :: S) a. CoSinkable binder => binder n l -> [a] -> NameMap n a -> NameMap l a Source #

Extend a map with multiple mappings (by repeatedly applying addNameBinder).

Note that the input list is expected to have at least the same number of elements as there are binders in the input pattern (generalized binder).

Since: 0.2.0

addNameBinderList :: forall (n :: S) (l :: S) a. NameBinderList n l -> [a] -> NameMap n a -> NameMap l a Source #

Extend a map with multiple mappings (by repeatedly applying addNameBinder).

Note that the input list is expected to have at least the same number of elements as there are binders in the input name binder list.

See also addNameBinders for a generalized version.

Since: 0.2.0

lookupName :: forall (n :: S) a. Name n -> NameMap n a -> a Source #

Looking up a name should always succeed.

Note that since Name is Sinkable, a name of scope n can be looked up in a NameMap for scope l whenever l extends n.

Since: 0.0.1

addNameBinder :: forall (n :: S) (l :: S) a. NameBinder n l -> a -> NameMap n a -> NameMap l a Source #

Extending a map with a single mapping.

Note that the scope parameter of the result differs from the initial map.

Since: 0.0.1

popNameBinder :: forall (n :: S) (l :: S) a. NameBinder n l -> NameMap l a -> NameMap n a Source #

Remove the mapping for a binder, shrinking the map back to the outer scope.

This is the inverse of addNameBinder, and is what a type checker wants when it leaves a binder it has entered.

Since: 0.3.1

withFreshNameBinderList Source #

Arguments

:: forall (n :: S) a r. Distinct n 
=> [a]

A value to bind to each fresh binder.

-> Scope n

The ambient scope.

-> NameMap n a

The map to extend.

-> (forall (l :: S). DExt n l => Scope l -> NameBinderList n l -> NameMap l a -> r) 
-> r 

Allocate a fresh binder for each element of a list, binding each element to its binder in the map.

The continuation receives the extended scope, the binders in the order of the input list, and the extended map. This is the list-shaped counterpart of withFresh, and saves a caller from threading the scope, the binders, and the map through a recursion by hand.

Since: 0.3.1

withFreshNameBinderListIn Source #

Arguments

:: forall (n :: S) a r. Distinct n 
=> NameRange

The reservation to allocate from.

-> [a]

A value to bind to each fresh binder.

-> Scope n

The ambient scope.

-> NameMap n a

The map to extend.

-> (forall (l :: S). DExt n l => Scope l -> NameBinderList n l -> NameMap l a -> r) 
-> r 

A version of withFreshNameBinderList that allocates within a given range (see withFreshIn). This is the bulk form of range-guarded allocation: pre-allocating the names of a whole unit at once and allocating them one at a time are the same operation at different granularity, so both extend the scope index faithfully.

Fails with error when the range is exhausted.

Since: 0.4.0

Raw types and operations

type Id = Int Source #

We will use Int for efficient representation of identifiers.

Since: 0.0.1

type RawName = Id Source #

Raw name is simply an identifier.

Since: 0.0.1

type RawScope = IntSet Source #

A raw scope is a set of raw names.

Since: 0.0.1

rawFreshName :: RawScope -> RawName Source #

\(O(\min(n, W))\). Generate a fresh raw name that does not appear in a given raw scope. The guard keeps allocation out of the negative range: names below zero are reserved for interned constants, allocated by an explicit policy (withFreshIn at a negative range) and never by this successor. Without the guard, a scope holding only negative names would hand out the successor of its maximum, which is a "fresh" name inside the constants' region and may collide with a constant not in this scope. A scope that holds maxBound is reported as exhausted rather than wrapped past, since the wrapped successor lands on an arbitrary small name that may well be taken.

Since: 0.0.1

data NameRange Source #

An inclusive reservation of a contiguous range of raw names.

A range is a bound on an allocator (see withFreshIn), not a set of names: its runtime content is two Ints. A range with lo > hi is empty.

Since: 0.4.0

Constructors

NameRange 

Fields

Instances

Instances details
Binary NameRange Source #

The two bounds. A range carries no scope index, so nothing is minted: this instance is layout metadata for the serialising layer.

Instance details

Defined in Control.Monad.Free.Foil.Binary

Show NameRange Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Eq NameRange Source # 
Instance details

Defined in Control.Monad.Foil.Internal

fullNameRange :: NameRange Source #

The range of all non-negative names.

On a scope without negative members, allocation within fullNameRange agrees with rawFreshName. The two diverge on a scope with negative members: rawFreshName allocates right above the maximum, wherever that lands, while fullNameRange clamps allocation to non-negative names.

Since: 0.4.0

rawFreshNameIn :: NameRange -> RawScope -> Maybe RawName Source #

\(O(\min(n, W))\). Generate a fresh raw name within a given range: the successor of the largest scope member inside the range, or the range's low end when no scope member lies inside the range. Returns Nothing when the range is exhausted (or empty to begin with).

The resulting name is fresh with respect to the whole scope: it differs from scope members inside the range by being greater, and from members outside the range by being inside it.

>>> rawFreshNameIn (NameRange 10 19) (IntSet.fromList [-5, 3, 12, 100])
Just 13
>>> rawFreshNameIn (NameRange 10 19) (IntSet.fromList [42])
Just 10
>>> rawFreshNameIn (NameRange 10 19) (IntSet.fromList [3, 19])
Nothing

Note that the implementation must not increment either bound of the range: lookupLT (hi + 1) would wrap around at hi = maxBound, and x + 1 would wrap around at x = hi = maxBound. Both are guarded here, and the property tests pin both cases.

Since: 0.4.0

rawMember :: RawName -> RawScope -> Bool Source #

Check if a raw name is contained in a raw scope.

Since: 0.0.1

Constraints

class ExtEndo (n :: S) Source #

Every scope is a (trivial) extension of itself.

Important: this class exists to assist tracking scope extensions for type variables of kind S. Users of the foil are not supposed to implement any instances of ExtEndo.

Since: 0.0.1

class (ExtEndo n => ExtEndo l) => Ext (n :: S) (l :: S) Source #

Some scopes are extensions of other scopes.

Important: this class exists to assist tracking scope extensions for type variables of kind S. Users of the foil are not supposed to implement any instances of Ext.

Since: 0.0.1

Instances

Instances details
(ExtEndo n => ExtEndo l) => Ext n l Source # 
Instance details

Defined in Control.Monad.Foil.Internal

class Distinct (n :: S) Source #

Scopes with distinct names.

Important: this class exists to explicitly mark scopes with distinct names. Users of the foil are not supposed to implement any instances of Distinct.

Since: 0.0.1

Instances

Instances details
Distinct 'VoidS Source # 
Instance details

Defined in Control.Monad.Foil.Internal

type DExt (n :: S) (l :: S) = (Distinct l, Ext n l) Source #

Scope extensions with distinct names.

Since: 0.0.1

class InjectName (e :: S -> Type) where Source #

Instances of this typeclass possess the ability to inject names. Usually, this is a variable data constructor.

Since: 0.0.1

Methods

injectName :: forall (n :: S). Name n -> e n Source #

Inject names into expressions.

Since: 0.0.1

Instances

Instances details
InjectName Expr Source # 
Instance details

Defined in Control.Monad.Foil.Example

Methods

injectName :: forall (n :: S). Name n -> Expr n Source #

InjectName (AST binder sig) Source # 
Instance details

Defined in Control.Monad.Free.Foil

Methods

injectName :: forall (n :: S). Name n -> AST binder sig n Source #

Kind-polymorphic sinkability

data RenamingsK (as :: LoT k) (bs :: LoT k) where Source #

One renaming per scope index of a kind-polymorphic type, which is what sinkabilityProofK threads through a value.

Since: 0.3.0

Constructors

RNil :: RenamingsK 'LoT0 'LoT0 
RCons :: forall {k1} (a :: S) (b :: S) (as1 :: LoT k1) (bs1 :: LoT k1). (Name a -> Name b) -> RenamingsK as1 bs1 -> RenamingsK (a ':&&: as1) (b ':&&: bs1) 
RSkip :: forall {k1} {k2} (as1 :: LoT k1) (bs1 :: LoT k1) (k3 :: k2). RenamingsK as1 bs1 -> RenamingsK (k3 ':&&: as1) (k3 ':&&: bs1) 

class SinkableK (f :: S -> k) where Source #

Sinkable for a type with any number of scope indices, and the class a pattern derives to obtain the foil's traversals. An instance is normally empty, leaving the generic implementation to walk the RepK of the type.

Since: 0.3.0

Minimal complete definition

Nothing

Methods

sinkabilityProofK :: forall (as :: LoT (S -> k)) (bs :: LoT (S -> k)) r. RenamingsK as bs -> (f :@@: as) -> (forall (cs :: LoT (S -> k)). RenamingsK as cs -> (f :@@: cs) -> r) -> r Source #

Rename every scope index of a value, in continuation-passing style.

Since: 0.3.0

default sinkabilityProofK :: forall (as :: LoT (S -> k)) (bs :: LoT (S -> k)) r. (GenericK f, GSinkableK (RepK f)) => RenamingsK as bs -> (f :@@: as) -> (forall (cs :: LoT (S -> k)). RenamingsK as cs -> (f :@@: cs) -> r) -> r Source #

Instances

Instances details
SinkableK Name Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> Type)) (bs :: LoT (S -> Type)) r. RenamingsK as bs -> (Name :@@: as) -> (forall (cs :: LoT (S -> Type)). RenamingsK as cs -> (Name :@@: cs) -> r) -> r Source #

(Bifunctor sig, CoSinkable binder, SinkableK binder) => SinkableK (AST binder sig :: S -> Type) Source # 
Instance details

Defined in Control.Monad.Free.Foil

Methods

sinkabilityProofK :: forall (as :: LoT (S -> Type)) (bs :: LoT (S -> Type)) r. RenamingsK as bs -> (AST binder sig :@@: as) -> (forall (cs :: LoT (S -> Type)). RenamingsK as cs -> (AST binder sig :@@: cs) -> r) -> r Source #

(Bifunctor sig, CoSinkable binder, SinkableK binder) => SinkableK (ScopedAST binder sig :: S -> Type) Source # 
Instance details

Defined in Control.Monad.Free.Foil

Methods

sinkabilityProofK :: forall (as :: LoT (S -> Type)) (bs :: LoT (S -> Type)) r. RenamingsK as bs -> (ScopedAST binder sig :@@: as) -> (forall (cs :: LoT (S -> Type)). RenamingsK as cs -> (ScopedAST binder sig :@@: cs) -> r) -> r Source #

SinkableK NameBinder Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (NameBinder :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (NameBinder :@@: cs) -> r) -> r Source #

SinkableK NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (NameBinderList :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (NameBinderList :@@: cs) -> r) -> r Source #

SinkableK NameBinders Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (NameBinders :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (NameBinders :@@: cs) -> r) -> r Source #

SinkableK U2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (U2 :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (U2 :@@: cs) -> r) -> r Source #

SinkableK V2 Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

sinkabilityProofK :: forall (as :: LoT (S -> S -> Type)) (bs :: LoT (S -> S -> Type)) r. RenamingsK as bs -> (V2 :@@: as) -> (forall (cs :: LoT (S -> S -> Type)). RenamingsK as cs -> (V2 :@@: cs) -> r) -> r Source #

sinkK :: forall {k} (f :: LoT k -> Type) (xs :: LoT (LoT k -> Type)) (as :: LoT (LoT k -> Type)) (bs :: LoT (LoT k -> Type)). GSinkableK f => RenamingsK xs as -> RenamingsK xs bs -> (f :@@: as) -> f :@@: bs Source #

Move a value between two scope index lists reached from a common one, as a coercion.

Since: 0.3.0

sinkabilityProof1 :: forall f (n :: S) (n' :: S). SinkableK f => (Name n -> Name n') -> f n -> f n' Source #

sinkabilityProofK at a type with exactly one scope index.

Since: 0.3.0

gsinkabilityProof1 :: forall f (n :: S) (n' :: S). GSinkableK f => (Name n -> Name n') -> f (n ':&&: 'LoT0) -> f (n' ':&&: 'LoT0) Source #

gsinkabilityProofK at a representation with one scope index.

Since: 0.3.0

gsinkabilityProof2 :: forall f (n :: S) (n' :: S) (l :: S) r. GSinkableK f => (Name n -> Name n') -> f (n ':&&: (l ':&&: 'LoT0)) -> (forall (l' :: S). (Name l -> Name l') -> f (n' ':&&: (l' ':&&: 'LoT0)) -> r) -> r Source #

gsinkabilityProofK at a representation with two scope indices, the shape of a pattern: the outer scope is renamed by the given function, and the inner one by the renaming handed to the continuation.

Since: 0.3.0

gsinkabilityProofK' :: forall {k} f (as :: LoT k) (bs :: LoT k). GSinkableK f => RenamingsK as bs -> f as -> f bs Source #

gsinkabilityProofK where the resulting index list is known, so that no continuation is needed.

Since: 0.3.0

class GSinkableK (p :: LoT k -> Type) where Source #

SinkableK on the Generics.Kind representation of a type, which is what the default sinkabilityProofK goes through.

Since: 0.3.0

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> p as -> (forall (cs :: LoT k). RenamingsK as cs -> p cs -> r) -> r Source #

Rename every scope index of a representation.

Since: 0.3.0

Instances

Instances details
GSinkableK (U1 :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> U1 as -> (forall (cs :: LoT k). RenamingsK as cs -> U1 cs -> r) -> r Source #

GSinkableK (V1 :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> V1 as -> (forall (cs :: LoT k). RenamingsK as cs -> V1 cs -> r) -> r Source #

(SinkableK f, ExtractRenamingK i, ExtractRenamingK j) => GSinkableK (Field ((('Kon f :: Atom k (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Field ((('Kon f :: Atom k (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) as -> (forall (cs :: LoT k). RenamingsK as cs -> Field ((('Kon f :: Atom k (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) cs -> r) -> r Source #

(SinkableK f, ExtractRenamingK i) => GSinkableK (Field (('Kon f :: Atom k (S -> Type)) ':@: 'Var i) :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Field (('Kon f :: Atom k (S -> Type)) ':@: 'Var i) as -> (forall (cs :: LoT k). RenamingsK as cs -> Field (('Kon f :: Atom k (S -> Type)) ':@: 'Var i) cs -> r) -> r Source #

(Bifunctor f, GSinkableK (Field x), GSinkableK (Field y)) => GSinkableK (Field ((('Kon f :: Atom k (Type -> Type -> Type)) ':@: x) ':@: y) :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Field ((('Kon f :: Atom k (Type -> Type -> Type)) ':@: x) ':@: y) as -> (forall (cs :: LoT k). RenamingsK as cs -> Field ((('Kon f :: Atom k (Type -> Type -> Type)) ':@: x) ':@: y) cs -> r) -> r Source #

(Functor f, GSinkableK (Field x)) => GSinkableK (Field (('Kon f :: Atom k (Type -> Type)) ':@: x) :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Field (('Kon f :: Atom k (Type -> Type)) ':@: x) as -> (forall (cs :: LoT k). RenamingsK as cs -> Field (('Kon f :: Atom k (Type -> Type)) ':@: x) cs -> r) -> r Source #

GSinkableK (Field ('Kon a :: Atom k Type) :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Field ('Kon a :: Atom k Type) as -> (forall (cs :: LoT k). RenamingsK as cs -> Field ('Kon a :: Atom k Type) cs -> r) -> r Source #

GSinkableK (Field ('Var a) :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Field ('Var a) as -> (forall (cs :: LoT k). RenamingsK as cs -> Field ('Var a) cs -> r) -> r Source #

(GSinkableK f, GSinkableK g) => GSinkableK (f :*: g :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> (f :*: g) as -> (forall (cs :: LoT k). RenamingsK as cs -> (f :*: g) cs -> r) -> r Source #

(GSinkableK f, GSinkableK g) => GSinkableK (f :+: g :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> (f :+: g) as -> (forall (cs :: LoT k). RenamingsK as cs -> (f :+: g) cs -> r) -> r Source #

GSinkableK f => GSinkableK ((a :~~: b) :=>: f :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> ((a :~~: b) :=>: f) as -> (forall (cs :: LoT k). RenamingsK as cs -> ((a :~~: b) :=>: f) cs -> r) -> r Source #

GSinkableK f => GSinkableK (Exists S f :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> Exists S f as -> (forall (cs :: LoT k). RenamingsK as cs -> Exists S f cs -> r) -> r Source #

GSinkableK f => GSinkableK (Exists k2 f :: LoT k1 -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k1) (bs :: LoT k1) r. RenamingsK as bs -> Exists k2 f as -> (forall (cs :: LoT k1). RenamingsK as cs -> Exists k2 f cs -> r) -> r Source #

GSinkableK f => GSinkableK (M1 i c f :: LoT k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. RenamingsK as bs -> M1 i c f as -> (forall (cs :: LoT k). RenamingsK as cs -> M1 i c f cs -> r) -> r Source #

SinkableK (f a) => GSinkableK (Field ((('Kon f :: Atom (S -> xs) (k1 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k1)) ':@: (Var0 :: Atom (S -> xs) S)) :: LoT (S -> xs) -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT (S -> xs)) (bs :: LoT (S -> xs)) r. RenamingsK as bs -> Field ((('Kon f :: Atom (S -> xs) (k1 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k1)) ':@: (Var0 :: Atom (S -> xs) S)) as -> (forall (cs :: LoT (S -> xs)). RenamingsK as cs -> Field ((('Kon f :: Atom (S -> xs) (k1 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k1)) ':@: (Var0 :: Atom (S -> xs) S)) cs -> r) -> r Source #

SinkableK (f a b) => GSinkableK (Field (((('Kon f :: Atom (S -> xs) (k2 -> k3 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k2)) ':@: ('Kon b :: Atom (S -> xs) k3)) ':@: (Var0 :: Atom (S -> xs) S)) :: LoT (S -> xs) -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

gsinkabilityProofK :: forall (as :: LoT (S -> xs)) (bs :: LoT (S -> xs)) r. RenamingsK as bs -> Field (((('Kon f :: Atom (S -> xs) (k2 -> k3 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k2)) ':@: ('Kon b :: Atom (S -> xs) k3)) ':@: (Var0 :: Atom (S -> xs) S)) as -> (forall (cs :: LoT (S -> xs)). RenamingsK as cs -> Field (((('Kon f :: Atom (S -> xs) (k2 -> k3 -> S -> Type)) ':@: ('Kon a :: Atom (S -> xs) k2)) ':@: ('Kon b :: Atom (S -> xs) k3)) ':@: (Var0 :: Atom (S -> xs) S)) cs -> r) -> r Source #

gsinkK :: forall {k} f (xs :: LoT k) (as :: LoT k) (bs :: LoT k). GSinkableK f => RenamingsK xs as -> RenamingsK xs bs -> f as -> f bs Source #

sinkK on a representation.

Since: 0.3.0

class ExtractRenamingK (i :: TyVar k S) where Source #

Reading one scope index out of a list of them, and putting a renaming back at that position. This is what lets a generic traversal work on the index a field actually mentions.

Since: 0.3.0

Methods

extractRenamingK :: forall (as :: LoT k) (bs :: LoT k). RenamingsK as bs -> Name (Interpret ('Var i) as) -> Name (Interpret ('Var i) bs) Source #

The renaming at this index.

Since: 0.3.0

putBackRenamingK :: forall (c :: S) (as :: LoT k) (bs :: LoT k). (Name (Interpret ('Var i) as) -> Name c) -> RenamingsK as bs -> RenamingsK as (PutBackLoT i c bs) Source #

Replace the renaming at this index.

Since: 0.3.0

Instances

Instances details
ExtractRenamingK ('VZ :: TyVar (S -> xs) S) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

extractRenamingK :: forall (as :: LoT (S -> xs)) (bs :: LoT (S -> xs)). RenamingsK as bs -> Name (Interpret ('Var ('VZ :: TyVar (S -> xs) S)) as) -> Name (Interpret ('Var ('VZ :: TyVar (S -> xs) S)) bs) Source #

putBackRenamingK :: forall (c :: S) (as :: LoT (S -> xs)) (bs :: LoT (S -> xs)). (Name (Interpret ('Var ('VZ :: TyVar (S -> xs) S)) as) -> Name c) -> RenamingsK as bs -> RenamingsK as (PutBackLoT ('VZ :: TyVar (S -> xs) S) c bs) Source #

ExtractRenamingK x2 => ExtractRenamingK ('VS x2 :: TyVar (x1 -> xs) S) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

extractRenamingK :: forall (as :: LoT (x1 -> xs)) (bs :: LoT (x1 -> xs)). RenamingsK as bs -> Name (Interpret ('Var ('VS x2 :: TyVar (x1 -> xs) S)) as) -> Name (Interpret ('Var ('VS x2 :: TyVar (x1 -> xs) S)) bs) Source #

putBackRenamingK :: forall (c :: S) (as :: LoT (x1 -> xs)) (bs :: LoT (x1 -> xs)). (Name (Interpret ('Var ('VS x2 :: TyVar (x1 -> xs) S)) as) -> Name c) -> RenamingsK as bs -> RenamingsK as (PutBackLoT ('VS x2 :: TyVar (x1 -> xs) S) c bs) Source #

extractTwoRenamingsK :: forall k (i :: TyVar k S) (j :: TyVar k S) (as :: LoT k) (bs :: LoT k). (ExtractRenamingK i, ExtractRenamingK j) => RenamingsK as bs -> RenamingsK (Interpret ('Var i) as ':&&: (Interpret ('Var j) as ':&&: 'LoT0)) (Interpret ('Var i) bs ':&&: (Interpret ('Var j) bs ':&&: 'LoT0)) Source #

extractRenamingK at two indices at once, as a pattern's traversal needs.

Since: 0.3.0

putBackTwoRenamingsK :: forall k (i :: TyVar k S) (j :: TyVar k S) (c1 :: S) (c2 :: S) (as :: LoT k) (bs :: LoT k). (ExtractRenamingK i, ExtractRenamingK j) => RenamingsK (Interpret ('Var i) as ':&&: (Interpret ('Var j) as ':&&: 'LoT0)) (c1 ':&&: (c2 ':&&: 'LoT0)) -> RenamingsK as bs -> RenamingsK as (PutBackLoT j c2 (PutBackLoT i c1 bs)) Source #

putBackRenamingK at two indices at once.

Since: 0.3.0

Kind-polymorphic types with binders

Generic version of withPattern

gunsafeWithPatternViaHasNameBinders Source #

Arguments

:: forall pattern f (o :: S) (n :: S) (l :: S) r. (Distinct o, GenericK pattern, GValidNameBinders pattern (RepK pattern), GHasNameBinders (RepK pattern)) 
=> (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r')

Processing of a single NameBinder, this will be applied to each binder in a pattern.

-> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z')

Result in case no binders are present. This can be seen as scope-indexed mempty.

-> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'')

Composition of results for nested binders/patterns. This can be seen as scope-indexed mappend.

-> Scope o

Ambient scope.

-> pattern n l

Pattern to process.

-> (forall (o' :: S). DExt o o' => f n l o o' -> pattern o o' -> Scope o' -> r)

Continuation, accepting the result for the entire pattern, a (possibly refreshed) pattern, and the scope extended by that pattern.

-> r 

Generic generalized processing of a pattern via GHasNameBinders.

This can be used as a default implementation of withPattern.

Since: 0.3.0

Manipulating nested NameBinders

class HasNameBinders (f :: S -> S -> Type) where Source #

If HasNameBinders f, then f n l is expected to act as a binder, introducing into scope n some local variables, extending it to scope l. This class allows to extract and modify the set of binders.

Since: 0.3.0

Minimal complete definition

Nothing

Methods

getNameBinders :: forall (n :: S) (l :: S). f n l -> NameBinders n l Source #

Extract a set of binders from a pattern.

Since: 0.3.0

unsafeSetNameBinders :: forall (n :: S) (l :: S) (l' :: S). f n l -> NameBinders n l' -> f n l' Source #

Replace binders in a pattern.

This function is unsafe, because it does not check if the new set of binders has the same size. It can therefore crash at runtime.

You should probably not use this. This is only used for gunsafeWithPatternViaHasNameBinders, which is then safe to use.

Since: 0.3.0

getNameBindersRaw :: forall (n :: S) (l :: S). f n l -> [RawName] Source #

Extract RawNames of all binders occurring in a pattern.

Since: 0.3.0

default getNameBindersRaw :: forall (n :: S) (l :: S). (GenericK f, GHasNameBinders (RepK f)) => f n l -> [RawName] Source #

reallyUnsafeSetNameBindersRaw :: forall (n :: S) (l :: S) (l' :: S). f n l -> [RawName] -> (f n l', [RawName]) Source #

This is a version of unsafeSetNameBinders that takes in a list of RawNames.

It does not check if the given list has enough elements. It does not check if the raw names are fresh in the scope n. It does not check if the raw names given are distinct.

You should never use this. This is only used for generic implementation of HasNameBinders.

Since: 0.3.0

default reallyUnsafeSetNameBindersRaw :: forall (n :: S) (l :: S) (l' :: S). (GenericK f, GValidNameBinders f (RepK f), GHasNameBinders (RepK f)) => f n l -> [RawName] -> (f n l', [RawName]) Source #

Instances

Instances details
HasNameBinders NameBinder Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

getNameBinders :: forall (n :: S) (l :: S). NameBinder n l -> NameBinders n l Source #

unsafeSetNameBinders :: forall (n :: S) (l :: S) (l' :: S). NameBinder n l -> NameBinders n l' -> NameBinder n l' Source #

getNameBindersRaw :: forall (n :: S) (l :: S). NameBinder n l -> [RawName] Source #

reallyUnsafeSetNameBindersRaw :: forall (n :: S) (l :: S) (l' :: S). NameBinder n l -> [RawName] -> (NameBinder n l', [RawName]) Source #

HasNameBinders NameBinderList Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

getNameBinders :: forall (n :: S) (l :: S). NameBinderList n l -> NameBinders n l Source #

unsafeSetNameBinders :: forall (n :: S) (l :: S) (l' :: S). NameBinderList n l -> NameBinders n l' -> NameBinderList n l' Source #

getNameBindersRaw :: forall (n :: S) (l :: S). NameBinderList n l -> [RawName] Source #

reallyUnsafeSetNameBindersRaw :: forall (n :: S) (l :: S) (l' :: S). NameBinderList n l -> [RawName] -> (NameBinderList n l', [RawName]) Source #

Generic

ggetNameBinders :: forall f (n :: S) (l :: S). (GenericK f, GHasNameBinders (RepK f)) => f n l -> NameBinders n l Source #

getNameBinders through the generic representation.

Since: 0.3.0

gunsafeSetNameBinders :: forall f (n :: S) (l :: S) (l' :: S). (GenericK f, GValidNameBinders f (RepK f), GHasNameBinders (RepK f)) => f n l -> NameBinders n l' -> f n l' Source #

unsafeSetNameBinders through the generic representation.

Since: 0.3.0

class GHasNameBinders (f :: k -> Type) where Source #

HasNameBinders on the Generics.Kind representation of a pattern.

Since: 0.3.0

Methods

ggetNameBindersRaw :: forall (as :: k). f as -> [RawName] Source #

The raw names the representation binds, in order.

Since: 0.3.0

greallyUnsafeSetNameBindersRaw :: forall (as :: k) (bs :: k). f as -> [RawName] -> (f bs, [RawName]) Source #

Replace those names, returning what is left of the list.

Since: 0.3.0

Instances

Instances details
GHasNameBinders (U1 :: k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: k). U1 as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: k) (bs :: k). U1 as -> [RawName] -> (U1 bs, [RawName]) Source #

GHasNameBinders (V1 :: k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: k). V1 as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: k) (bs :: k). V1 as -> [RawName] -> (V1 bs, [RawName]) Source #

(GHasNameBinders f, GHasNameBinders g) => GHasNameBinders (f :*: g :: k -> Type) Source #

A caveat. This instance treats the two factors as nested binders, and does not reject parallel ones:

data BadPattern n l = BadPattern (NameBinder n l) (NameBinder n l)

The intended shape is a chain, in which each binder extends the scope the next one starts from:

data GoodPattern n l = forall i. GoodPattern (NameBinder n i) (NameBinder i l)

Template Haskell never generates parallel binders, and writing one by hand takes deliberate effort, so this is unlikely to be reached by accident. Detecting and rejecting such a pattern would still be better.

Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: k). (f :*: g) as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: k) (bs :: k). (f :*: g) as -> [RawName] -> ((f :*: g) bs, [RawName]) Source #

(GHasNameBinders f, GHasNameBinders g) => GHasNameBinders (f :+: g :: k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: k). (f :+: g) as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: k) (bs :: k). (f :+: g) as -> [RawName] -> ((f :+: g) bs, [RawName]) Source #

GHasNameBinders f => GHasNameBinders (M1 i c f :: k -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: k). M1 i c f as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: k) (bs :: k). M1 i c f as -> [RawName] -> (M1 i c f bs, [RawName]) Source #

HasNameBinders f => GHasNameBinders (Field ((('Kon f :: Atom d (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) :: LoT d -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: LoT d). Field ((('Kon f :: Atom d (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: LoT d) (bs :: LoT d). Field ((('Kon f :: Atom d (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) as -> [RawName] -> (Field ((('Kon f :: Atom d (S -> S -> Type)) ':@: 'Var i) ':@: 'Var j) bs, [RawName]) Source #

GHasNameBinders (Field (('Kon f :: Atom d (k1 -> Type)) ':@: 'Var i) :: LoT d -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: LoT d). Field (('Kon f :: Atom d (k1 -> Type)) ':@: 'Var i) as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: LoT d) (bs :: LoT d). Field (('Kon f :: Atom d (k1 -> Type)) ':@: 'Var i) as -> [RawName] -> (Field (('Kon f :: Atom d (k1 -> Type)) ':@: 'Var i) bs, [RawName]) Source #

GHasNameBinders (Field ('Kon a :: Atom d Type) :: LoT d -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: LoT d). Field ('Kon a :: Atom d Type) as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: LoT d) (bs :: LoT d). Field ('Kon a :: Atom d Type) as -> [RawName] -> (Field ('Kon a :: Atom d Type) bs, [RawName]) Source #

GHasNameBinders (Field ('Var x) :: LoT d -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: LoT d). Field ('Var x) as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: LoT d) (bs :: LoT d). Field ('Var x) as -> [RawName] -> (Field ('Var x) bs, [RawName]) Source #

GHasNameBinders f => GHasNameBinders (('Var i :~~: 'Var j) :=>: f :: LoT d -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: LoT d). (('Var i :~~: 'Var j) :=>: f) as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: LoT d) (bs :: LoT d). (('Var i :~~: 'Var j) :=>: f) as -> [RawName] -> ((('Var i :~~: 'Var j) :=>: f) bs, [RawName]) Source #

GHasNameBinders f => GHasNameBinders (Exists k f :: LoT d -> Type) Source # 
Instance details

Defined in Control.Monad.Foil.Internal

Methods

ggetNameBindersRaw :: forall (as :: LoT d). Exists k f as -> [RawName] Source #

greallyUnsafeSetNameBindersRaw :: forall (as :: LoT d) (bs :: LoT d). Exists k f as -> [RawName] -> (Exists k f bs, [RawName]) Source #