packages feed

free-foil 0.0.3 → 0.1.0

raw patch · 13 files changed

+1058/−227 lines, 13 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Monad.Free.Foil: instance (forall (l :: Control.Monad.Foil.Internal.S). Control.DeepSeq.NFData (Control.Monad.Free.Foil.AST sig l)) => Control.DeepSeq.NFData (Control.Monad.Free.Foil.ScopedAST sig n)
- Control.Monad.Free.Foil: instance (forall scope term. (Control.DeepSeq.NFData scope, Control.DeepSeq.NFData term) => Control.DeepSeq.NFData (sig scope term)) => Control.DeepSeq.NFData (Control.Monad.Free.Foil.AST sig n)
- Control.Monad.Free.Foil: instance Control.Monad.Foil.Internal.InjectName (Control.Monad.Free.Foil.AST sig)
- Control.Monad.Free.Foil: instance Data.Bifunctor.Bifunctor sig => Control.Monad.Foil.Internal.Sinkable (Control.Monad.Free.Foil.AST sig)
- Control.Monad.Free.Foil: instance Data.Bifunctor.Bifunctor sig => Control.Monad.Foil.Relative.RelMonad Control.Monad.Foil.Internal.Name (Control.Monad.Free.Foil.AST sig)
- Control.Monad.Free.Foil: instance GHC.Generics.Generic (Control.Monad.Free.Foil.AST sig n)
- Control.Monad.Free.Foil.Example: pattern LamE :: () => NameBinder n l -> AST ExprF l -> AST ExprF n
+ Control.Monad.Foil: ($dmunifyInPattern) :: (UnifiableInPattern a, Eq a) => a -> a -> Bool
+ Control.Monad.Foil: [NotUnifiable] :: forall (pattern :: S -> S -> Type) (n :: S) (l :: S) (r :: S). UnifyNameBinders pattern n l r
+ Control.Monad.Foil: [RenameBothBinders] :: forall (n :: S) (lr :: S) (l :: S) (r :: S) (pattern :: S -> S -> Type). NameBinders n lr -> (NameBinder n l -> NameBinder n lr) -> (NameBinder n r -> NameBinder n lr) -> UnifyNameBinders pattern n l r
+ Control.Monad.Foil: absurd2 :: forall (n :: S) (l :: S) a. V2 n l -> a
+ Control.Monad.Foil: andThenUnifyNameBinders :: 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' -> (NameBinder l r, NameBinder l' r') -> UnifyNameBinders pattern n r r'
+ Control.Monad.Foil: andThenUnifyPatterns :: forall pattern (l :: S) (l' :: S) (n :: S) (r :: S) (r' :: S). (UnifiablePattern pattern, Distinct l, Distinct l') => UnifyNameBinders pattern n l l' -> (pattern l r, pattern l' r') -> UnifyNameBinders pattern n r r'
+ Control.Monad.Foil: class UnifiableInPattern a
+ Control.Monad.Foil: class CoSinkable pattern => UnifiablePattern (pattern :: S -> S -> Type)
+ Control.Monad.Foil: data NameBinders (n :: S) (l :: S)
+ Control.Monad.Foil: data V2 (n :: S) (l :: S)
+ Control.Monad.Foil: emptyNameBinders :: forall (n :: S). NameBinders n n
+ Control.Monad.Foil: extendScopePattern :: forall (n :: S) pattern (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> Scope n -> Scope l
+ Control.Monad.Foil: mergeNameBinders :: forall (n :: S) (i :: S) (l :: S). NameBinders n i -> NameBinders i l -> NameBinders n l
+ Control.Monad.Foil: namesOfPattern :: forall pattern (n :: S) (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> [Name l]
+ Control.Monad.Foil: unifyInPattern :: UnifiableInPattern a => a -> a -> Bool
+ Control.Monad.Foil: unifyPatterns :: forall (n :: S) (l :: S) (r :: S). (UnifiablePattern pattern, Distinct n) => pattern n l -> pattern n r -> UnifyNameBinders pattern n l r
+ Control.Monad.Foil: unsinkNamePattern :: forall pattern (n :: S) (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> Name l -> Maybe (Name n)
+ Control.Monad.Foil: withFreshPattern :: forall (o :: S) pattern (e :: S -> Type) (n :: S) (l :: S) r. (Distinct o, CoSinkable pattern, Sinkable e, InjectName e) => Scope o -> pattern n l -> (forall (o' :: S). DExt o o' => (Substitution e n o -> Substitution e l o') -> pattern o o' -> r) -> r
+ Control.Monad.Foil: withPattern :: forall (o :: S) f (n :: S) (l :: S) r. (CoSinkable pattern, 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 -> pattern n l -> (forall (o' :: S). DExt o o' => f n l o o' -> pattern o o' -> r) -> r
+ Control.Monad.Foil: withRefreshedPattern :: forall (o :: S) pattern (e :: S -> Type) (n :: S) (l :: S) r. (Distinct o, CoSinkable pattern, Sinkable e, InjectName e) => Scope o -> pattern n l -> (forall (o' :: S). DExt o o' => (Substitution e n o -> Substitution e l o') -> pattern o o' -> r) -> r
+ Control.Monad.Foil: 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' -> r) -> r
+ Control.Monad.Foil.Internal: ($dmunifyInPattern) :: (UnifiableInPattern a, Eq a) => a -> a -> Bool
+ Control.Monad.Foil.Internal: ExtendScope :: (Scope n -> Scope l) -> ExtendScope (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: NamesOf :: [Name l] -> NamesOf (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: UnsafeNameBinders :: IntSet -> NameBinders (n :: S) (l :: S)
+ Control.Monad.Foil.Internal: UnsinkName :: (Name l -> Maybe (Name n)) -> UnsinkName (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: WithRefreshedPattern :: (Substitution e n o -> Substitution e l o') -> WithRefreshedPattern (e :: S -> Type) (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: WithRefreshedPattern' :: ((Name n -> e o) -> Name l -> e o') -> WithRefreshedPattern' (e :: S -> Type) (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: [NameBinderListCons] :: forall (n :: S) (i :: S) (l :: S). NameBinder n i -> NameBinderList i l -> NameBinderList n l
+ Control.Monad.Foil.Internal: [NameBinderListEmpty] :: forall (n :: S). NameBinderList n n
+ Control.Monad.Foil.Internal: [NotUnifiable] :: forall (pattern :: S -> S -> Type) (n :: S) (l :: S) (r :: S). UnifyNameBinders pattern n l r
+ Control.Monad.Foil.Internal: [RenameBothBinders] :: forall (n :: S) (lr :: S) (l :: S) (r :: S) (pattern :: S -> S -> Type). NameBinders n lr -> (NameBinder n l -> NameBinder n lr) -> (NameBinder n r -> NameBinder n lr) -> UnifyNameBinders pattern n l r
+ Control.Monad.Foil.Internal: [U2] :: forall (n :: S). U2 n n
+ Control.Monad.Foil.Internal: absurd2 :: forall (n :: S) (l :: S) a. V2 n l -> a
+ Control.Monad.Foil.Internal: andThenUnifyNameBinders :: 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' -> (NameBinder l r, NameBinder l' r') -> UnifyNameBinders pattern n r r'
+ Control.Monad.Foil.Internal: andThenUnifyPatterns :: forall pattern (l :: S) (l' :: S) (n :: S) (r :: S) (r' :: S). (UnifiablePattern pattern, Distinct l, Distinct l') => UnifyNameBinders pattern n l l' -> (pattern l r, pattern l' r') -> UnifyNameBinders pattern n r r'
+ Control.Monad.Foil.Internal: class UnifiableInPattern a
+ Control.Monad.Foil.Internal: class CoSinkable pattern => UnifiablePattern (pattern :: S -> S -> Type)
+ Control.Monad.Foil.Internal: 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''
+ Control.Monad.Foil.Internal: 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''
+ Control.Monad.Foil.Internal: 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''
+ Control.Monad.Foil.Internal: 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''
+ Control.Monad.Foil.Internal: 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''
+ Control.Monad.Foil.Internal: data NameBinderList (n :: S) (l :: S)
+ Control.Monad.Foil.Internal: data U2 (n :: S) (l :: S)
+ Control.Monad.Foil.Internal: data V2 (n :: S) (l :: S)
+ Control.Monad.Foil.Internal: emptyNameBinders :: forall (n :: S). NameBinders n n
+ Control.Monad.Foil.Internal: extendScopePattern :: forall (n :: S) pattern (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> Scope n -> Scope l
+ Control.Monad.Foil.Internal: fromNameBindersList :: forall (n :: S) (l :: S). NameBinderList n l -> NameBinders n l
+ Control.Monad.Foil.Internal: idExtendScope :: forall (n :: S) (o :: S) (o' :: S). ExtendScope n n o o'
+ Control.Monad.Foil.Internal: idNamesOf :: forall (n :: S) (o :: S) (o' :: S). NamesOf n n o o'
+ Control.Monad.Foil.Internal: idUnsinkName :: forall (n :: S) (o :: S) (o' :: S). UnsinkName n n o o'
+ Control.Monad.Foil.Internal: idWithRefreshedPattern :: forall (e :: S -> Type) (o :: S) (o' :: S) (n :: S). (Sinkable e, DExt o o') => WithRefreshedPattern e n n o o'
+ Control.Monad.Foil.Internal: idWithRefreshedPattern' :: forall (e :: S -> Type) (o :: S) (o' :: S) (n :: S). (Sinkable e, DExt o o') => WithRefreshedPattern' e n n o o'
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.CoSinkable Control.Monad.Foil.Internal.NameBinderList
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.CoSinkable Control.Monad.Foil.Internal.NameBinders
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.CoSinkable Control.Monad.Foil.Internal.U2
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.CoSinkable Control.Monad.Foil.Internal.V2
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.UnifiablePattern Control.Monad.Foil.Internal.NameBinder
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.UnifiablePattern Control.Monad.Foil.Internal.U2
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.UnifiablePattern Control.Monad.Foil.Internal.V2
+ Control.Monad.Foil.Internal: mergeNameBinders :: forall (n :: S) (i :: S) (l :: S). NameBinders n i -> NameBinders i l -> NameBinders n l
+ Control.Monad.Foil.Internal: nameBindersList :: forall (n :: S) (l :: S). NameBinders n l -> NameBinderList n l
+ Control.Monad.Foil.Internal: nameBindersSingleton :: forall (n :: S) (l :: S). NameBinder n l -> NameBinders n l
+ Control.Monad.Foil.Internal: namesOfPattern :: forall pattern (n :: S) (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> [Name l]
+ Control.Monad.Foil.Internal: newtype ExtendScope (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: newtype NameBinders (n :: S) (l :: S)
+ Control.Monad.Foil.Internal: newtype NamesOf (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: newtype UnsinkName (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: newtype WithRefreshedPattern (e :: S -> Type) (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: newtype WithRefreshedPattern' (e :: S -> Type) (n :: S) (l :: S) (o :: S) (o' :: S)
+ Control.Monad.Foil.Internal: unifyInPattern :: UnifiableInPattern a => a -> a -> Bool
+ Control.Monad.Foil.Internal: unifyPatterns :: forall (n :: S) (l :: S) (r :: S). (UnifiablePattern pattern, Distinct n) => pattern n l -> pattern n r -> UnifyNameBinders pattern n l r
+ Control.Monad.Foil.Internal: unsafeEqPattern :: forall pattern (n :: S) (l :: S) (n' :: S) (l' :: S). (UnifiablePattern pattern, Distinct n) => pattern n l -> pattern n' l' -> Bool
+ Control.Monad.Foil.Internal: unsafeMergeNameBinders :: forall (a :: S) (b :: S) (c :: S) (d :: S) (n :: S) (l :: S). NameBinders a b -> NameBinders c d -> NameBinders n l
+ Control.Monad.Foil.Internal: 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''
+ Control.Monad.Foil.Internal: unsinkNamePattern :: forall pattern (n :: S) (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> Name l -> Maybe (Name n)
+ Control.Monad.Foil.Internal: withFreshPattern :: forall (o :: S) pattern (e :: S -> Type) (n :: S) (l :: S) r. (Distinct o, CoSinkable pattern, Sinkable e, InjectName e) => Scope o -> pattern n l -> (forall (o' :: S). DExt o o' => (Substitution e n o -> Substitution e l o') -> pattern o o' -> r) -> r
+ Control.Monad.Foil.Internal: withPattern :: forall (o :: S) f (n :: S) (l :: S) r. (CoSinkable pattern, 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 -> pattern n l -> (forall (o' :: S). DExt o o' => f n l o o' -> pattern o o' -> r) -> r
+ Control.Monad.Foil.Internal: withRefreshedPattern :: forall (o :: S) pattern (e :: S -> Type) (n :: S) (l :: S) r. (Distinct o, CoSinkable pattern, Sinkable e, InjectName e) => Scope o -> pattern n l -> (forall (o' :: S). DExt o o' => (Substitution e n o -> Substitution e l o') -> pattern o o' -> r) -> r
+ Control.Monad.Foil.Internal: 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' -> r) -> r
+ Control.Monad.Foil.TH.MkFoilData: mkFoilPattern :: Name -> Name -> Q [Dec]
+ Control.Monad.Foil.TH.MkFromFoil: mkFromFoilPattern :: Name -> Name -> Q [Dec]
+ Control.Monad.Foil.TH.MkInstancesFoil: deriveCoSinkable :: Name -> Name -> Q [Dec]
+ Control.Monad.Foil.TH.MkInstancesFoil: deriveUnifiablePattern :: Name -> Name -> Q [Dec]
+ Control.Monad.Foil.TH.MkToFoil: mkExtendScopeFoilPattern :: Name -> Name -> Q [Dec]
+ Control.Monad.Foil.TH.MkToFoil: mkToFoilPattern :: Name -> Name -> Q [Dec]
+ Control.Monad.Foil.TH.MkToFoil: mkToFoilTerm :: Name -> Name -> Name -> Name -> Q [Dec]
+ Control.Monad.Foil.TH.MkToFoil: mkWithRefreshedFoilPattern :: Name -> Name -> Q [Dec]
+ Control.Monad.Free.Foil: instance (Data.Bifunctor.Bifunctor sig, Control.Monad.Foil.Internal.CoSinkable binder) => Control.Monad.Foil.Internal.Sinkable (Control.Monad.Free.Foil.AST binder sig)
+ Control.Monad.Free.Foil: instance (Data.Bifunctor.Bifunctor sig, Control.Monad.Foil.Internal.CoSinkable binder) => Control.Monad.Foil.Relative.RelMonad Control.Monad.Foil.Internal.Name (Control.Monad.Free.Foil.AST binder sig)
+ Control.Monad.Free.Foil: instance (forall (x :: Control.Monad.Foil.Internal.S) (y :: Control.Monad.Foil.Internal.S). Control.DeepSeq.NFData (binder x y), forall (l :: Control.Monad.Foil.Internal.S). Control.DeepSeq.NFData (Control.Monad.Free.Foil.AST binder sig l)) => Control.DeepSeq.NFData (Control.Monad.Free.Foil.ScopedAST binder sig n)
+ Control.Monad.Free.Foil: instance (forall (x :: Control.Monad.Foil.Internal.S) (y :: Control.Monad.Foil.Internal.S). Control.DeepSeq.NFData (binder x y), forall scope term. (Control.DeepSeq.NFData scope, Control.DeepSeq.NFData term) => Control.DeepSeq.NFData (sig scope term)) => Control.DeepSeq.NFData (Control.Monad.Free.Foil.AST binder sig n)
+ Control.Monad.Free.Foil: instance Control.Monad.Foil.Internal.InjectName (Control.Monad.Free.Foil.AST binder sig)
+ Control.Monad.Free.Foil: instance GHC.Generics.Generic (Control.Monad.Free.Foil.AST binder sig n)
+ Control.Monad.Free.Foil.Example: pattern LamE :: () => binder n l -> AST binder ExprF l -> AST binder ExprF n
- Control.Monad.Foil: [RenameLeftNameBinder] :: forall (n :: S) (l :: S) (r :: S). (NameBinder n l -> NameBinder n r) -> UnifyNameBinders n l r
+ Control.Monad.Foil: [RenameLeftNameBinder] :: forall (n :: S) (r :: S) (l :: S) (pattern :: S -> S -> Type). NameBinders n r -> (NameBinder n l -> NameBinder n r) -> UnifyNameBinders pattern n l r
- Control.Monad.Foil: [RenameRightNameBinder] :: forall (n :: S) (r :: S) (l :: S). (NameBinder n r -> NameBinder n l) -> UnifyNameBinders n l r
+ Control.Monad.Foil: [RenameRightNameBinder] :: forall (n :: S) (l :: S) (r :: S) (pattern :: S -> S -> Type). NameBinders n l -> (NameBinder n r -> NameBinder n l) -> UnifyNameBinders pattern n l r
- Control.Monad.Foil: [SameNameBinders] :: forall (n :: S) (l :: S). UnifyNameBinders n l l
+ Control.Monad.Foil: [SameNameBinders] :: forall (n :: S) (l :: S) (pattern :: S -> S -> Type). NameBinders n l -> UnifyNameBinders pattern n l l
- Control.Monad.Foil: assertDistinct :: forall (n :: S) (l :: S). Distinct n => NameBinder n l -> DistinctEvidence l
+ Control.Monad.Foil: assertDistinct :: forall (n :: S) pattern (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> DistinctEvidence l
- Control.Monad.Foil: assertExt :: forall (n :: S) (l :: S). NameBinder n l -> ExtEvidence n l
+ Control.Monad.Foil: assertExt :: forall pattern (n :: S) (l :: S). CoSinkable pattern => pattern n l -> ExtEvidence n l
- Control.Monad.Foil: data UnifyNameBinders (n :: S) (l :: S) (r :: S)
+ Control.Monad.Foil: data UnifyNameBinders (pattern :: S -> S -> Type) (n :: S) (l :: S) (r :: S)
- Control.Monad.Foil: unifyNameBinders :: forall (i :: S) (l :: S) (r :: S). NameBinder i l -> NameBinder i r -> UnifyNameBinders i l r
+ Control.Monad.Foil: unifyNameBinders :: forall (i :: S) (l :: S) (r :: S) (pattern :: S -> S -> Type). Distinct i => NameBinder i l -> NameBinder i r -> UnifyNameBinders pattern i l r
- Control.Monad.Foil.Internal: [RenameLeftNameBinder] :: forall (n :: S) (l :: S) (r :: S). (NameBinder n l -> NameBinder n r) -> UnifyNameBinders n l r
+ Control.Monad.Foil.Internal: [RenameLeftNameBinder] :: forall (n :: S) (r :: S) (l :: S) (pattern :: S -> S -> Type). NameBinders n r -> (NameBinder n l -> NameBinder n r) -> UnifyNameBinders pattern n l r
- Control.Monad.Foil.Internal: [RenameRightNameBinder] :: forall (n :: S) (r :: S) (l :: S). (NameBinder n r -> NameBinder n l) -> UnifyNameBinders n l r
+ Control.Monad.Foil.Internal: [RenameRightNameBinder] :: forall (n :: S) (l :: S) (r :: S) (pattern :: S -> S -> Type). NameBinders n l -> (NameBinder n r -> NameBinder n l) -> UnifyNameBinders pattern n l r
- Control.Monad.Foil.Internal: [SameNameBinders] :: forall (n :: S) (l :: S). UnifyNameBinders n l l
+ Control.Monad.Foil.Internal: [SameNameBinders] :: forall (n :: S) (l :: S) (pattern :: S -> S -> Type). NameBinders n l -> UnifyNameBinders pattern n l l
- Control.Monad.Foil.Internal: assertDistinct :: forall (n :: S) (l :: S). Distinct n => NameBinder n l -> DistinctEvidence l
+ Control.Monad.Foil.Internal: assertDistinct :: forall (n :: S) pattern (l :: S). (Distinct n, CoSinkable pattern) => pattern n l -> DistinctEvidence l
- Control.Monad.Foil.Internal: assertExt :: forall (n :: S) (l :: S). NameBinder n l -> ExtEvidence n l
+ Control.Monad.Foil.Internal: assertExt :: forall pattern (n :: S) (l :: S). CoSinkable pattern => pattern n l -> ExtEvidence n l
- Control.Monad.Foil.Internal: data UnifyNameBinders (n :: S) (l :: S) (r :: S)
+ Control.Monad.Foil.Internal: data UnifyNameBinders (pattern :: S -> S -> Type) (n :: S) (l :: S) (r :: S)
- Control.Monad.Foil.Internal: unifyNameBinders :: forall (i :: S) (l :: S) (r :: S). NameBinder i l -> NameBinder i r -> UnifyNameBinders i l r
+ Control.Monad.Foil.Internal: unifyNameBinders :: forall (i :: S) (l :: S) (r :: S) (pattern :: S -> S -> Type). Distinct i => NameBinder i l -> NameBinder i r -> UnifyNameBinders pattern i l r
- Control.Monad.Free.Foil: [Node] :: forall (sig :: Type -> Type -> Type) (n :: S). sig (ScopedAST sig n) (AST sig n) -> AST sig n
+ Control.Monad.Free.Foil: [Node] :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S). sig (ScopedAST binder sig n) (AST binder sig n) -> AST binder sig n
- Control.Monad.Free.Foil: [ScopedAST] :: forall (n :: S) (l :: S) (sig :: Type -> Type -> Type). NameBinder n l -> AST sig l -> ScopedAST sig n
+ Control.Monad.Free.Foil: [ScopedAST] :: forall (binder :: S -> S -> Type) (n :: S) (l :: S) (sig :: Type -> Type -> Type). binder n l -> AST binder sig l -> ScopedAST binder sig n
- Control.Monad.Free.Foil: [Var] :: forall (n :: S) (sig :: Type -> Type -> Type). Name n -> AST sig n
+ Control.Monad.Free.Foil: [Var] :: forall (n :: S) (binder :: S -> S -> Type) (sig :: Type -> Type -> Type). Name n -> AST binder sig n
- Control.Monad.Free.Foil: alphaEquiv :: forall (sig :: Type -> Type -> Type) (n :: S). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n) => Scope n -> AST sig n -> AST sig n -> Bool
+ Control.Monad.Free.Foil: alphaEquiv :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool
- Control.Monad.Free.Foil: alphaEquivRefreshed :: forall (sig :: Type -> Type -> Type) (n :: S). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n) => Scope n -> AST sig n -> AST sig n -> Bool
+ Control.Monad.Free.Foil: alphaEquivRefreshed :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool
- Control.Monad.Free.Foil: alphaEquivScoped :: forall (sig :: Type -> Type -> Type) (n :: S). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n) => Scope n -> ScopedAST sig n -> ScopedAST sig n -> Bool
+ Control.Monad.Free.Foil: alphaEquivScoped :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n -> Bool
- Control.Monad.Free.Foil: convertFromAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (rawIdent -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> AST sig n -> rawTerm
+ Control.Monad.Free.Foil: convertFromAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (forall (x :: S) (y :: S). () => (Int -> rawIdent) -> binder x y -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> AST binder sig n -> rawTerm
- Control.Monad.Free.Foil: convertFromScopedAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (rawIdent -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> ScopedAST sig n -> (rawPattern, rawScopedTerm)
+ Control.Monad.Free.Foil: convertFromScopedAST :: forall sig rawPattern rawScopedTerm rawTerm rawIdent binder (n :: S). Bifunctor sig => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm) -> (rawIdent -> rawTerm) -> (forall (x :: S) (y :: S). () => (Int -> rawIdent) -> binder x y -> rawPattern) -> (rawTerm -> rawScopedTerm) -> (Int -> rawIdent) -> ScopedAST binder sig n -> (rawPattern, rawScopedTerm)
- Control.Monad.Free.Foil: convertToAST :: forall (n :: S) sig rawIdent rawTerm rawPattern rawScopedTerm. (Distinct n, Bifunctor sig, Ord rawIdent) => (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm)) -> (rawPattern -> Maybe rawIdent) -> (rawScopedTerm -> rawTerm) -> Scope n -> Map rawIdent (Name n) -> rawTerm -> AST sig n
+ Control.Monad.Free.Foil: convertToAST :: forall (n :: S) sig rawIdent binder rawTerm rawPattern rawScopedTerm. (Distinct n, Bifunctor sig, Ord rawIdent, CoSinkable binder) => (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm)) -> (forall (x :: S) z. Distinct x => Scope x -> Map rawIdent (Name x) -> rawPattern -> (forall (y :: S). DExt x y => binder x y -> Map rawIdent (Name y) -> z) -> z) -> (rawScopedTerm -> rawTerm) -> Scope n -> Map rawIdent (Name n) -> rawTerm -> AST binder sig n
- Control.Monad.Free.Foil: convertToScopedAST :: forall (n :: S) sig rawIdent rawTerm rawPattern rawScopedTerm. (Distinct n, Bifunctor sig, Ord rawIdent) => (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm)) -> (rawPattern -> Maybe rawIdent) -> (rawScopedTerm -> rawTerm) -> Scope n -> Map rawIdent (Name n) -> (rawPattern, rawScopedTerm) -> ScopedAST sig n
+ Control.Monad.Free.Foil: convertToScopedAST :: forall (n :: S) sig rawIdent binder rawTerm rawPattern rawScopedTerm. (Distinct n, Bifunctor sig, Ord rawIdent, CoSinkable binder) => (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm)) -> (forall (x :: S) z. Distinct x => Scope x -> Map rawIdent (Name x) -> rawPattern -> (forall (y :: S). DExt x y => binder x y -> Map rawIdent (Name y) -> z) -> z) -> (rawScopedTerm -> rawTerm) -> Scope n -> Map rawIdent (Name n) -> (rawPattern, rawScopedTerm) -> ScopedAST binder sig n
- Control.Monad.Free.Foil: data AST (sig :: Type -> Type -> Type) (n :: S)
+ Control.Monad.Free.Foil: data AST (binder :: S -> S -> Type) (sig :: Type -> Type -> Type) (n :: S)
- Control.Monad.Free.Foil: data ScopedAST (sig :: Type -> Type -> Type) (n :: S)
+ Control.Monad.Free.Foil: data ScopedAST (binder :: S -> S -> Type) (sig :: Type -> Type -> Type) (n :: S)
- Control.Monad.Free.Foil: refreshAST :: forall (sig :: Type -> Type -> Type) (n :: S). (Bifunctor sig, Distinct n) => Scope n -> AST sig n -> AST sig n
+ Control.Monad.Free.Foil: refreshAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder) => Scope n -> AST binder sig n -> AST binder sig n
- Control.Monad.Free.Foil: refreshScopedAST :: forall (sig :: Type -> Type -> Type) (n :: S). (Bifunctor sig, Distinct n) => Scope n -> ScopedAST sig n -> ScopedAST sig n
+ Control.Monad.Free.Foil: refreshScopedAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n
- Control.Monad.Free.Foil: substitute :: forall (sig :: Type -> Type -> Type) (o :: S) (i :: S). (Bifunctor sig, Distinct o) => Scope o -> Substitution (AST sig) i o -> AST sig i -> AST sig o
+ Control.Monad.Free.Foil: substitute :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o
- Control.Monad.Free.Foil: substituteRefreshed :: forall (sig :: Type -> Type -> Type) (o :: S) (i :: S). (Bifunctor sig, Distinct o) => Scope o -> Substitution (AST sig) i o -> AST sig i -> AST sig o
+ Control.Monad.Free.Foil: substituteRefreshed :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o
- Control.Monad.Free.Foil: unsafeEqAST :: forall (sig :: Type -> Type -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig) => AST sig n -> AST sig l -> Bool
+ Control.Monad.Free.Foil: unsafeEqAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig, UnifiablePattern binder, Distinct n, Distinct l) => AST binder sig n -> AST binder sig l -> Bool
- Control.Monad.Free.Foil: unsafeEqScopedAST :: forall (sig :: Type -> Type -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig) => ScopedAST sig n -> ScopedAST sig l -> Bool
+ Control.Monad.Free.Foil: unsafeEqScopedAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig, UnifiablePattern binder, Distinct n, Distinct l) => ScopedAST binder sig n -> ScopedAST binder sig l -> Bool
- Control.Monad.Free.Foil.Example: pattern AppE :: AST ExprF n -> AST ExprF n -> AST ExprF n
+ Control.Monad.Free.Foil.Example: pattern AppE :: AST binder ExprF n -> AST binder ExprF n -> AST binder ExprF n
- Control.Monad.Free.Foil.Example: type Expr = AST ExprF
+ Control.Monad.Free.Foil.Example: type Expr = AST NameBinder ExprF

Files

ChangeLog.md view
@@ -1,5 +1,33 @@ # CHANGELOG for `free-foil` +# 0.1.0 — 2024-08-18++- Generalize functions for binders, support general patterns (see [#16](https://github.com/fizruk/free-foil/pull/16))++  - Add `withPattern` method to `CoSinkable`. It can be seen as a CPS-style traversal over binders in a pattern.+    Our Template Haskell support covers generation of `withPattern`,+    so normally the user does not have to think about it.++  - Generalize many functions to work with arbitrary patterns, not just `NameBinder`:++    - `withFreshPattern` — to+    - `withRefreshedPattern` and `withRefreshedPattern'`+    - `extendScopePattern` — extend a given scope with all binders in a given pattern+    - `namesOfPattern` — collect all names from a pattern+    - `unsinkNamePattern` — try to unsink names from a scope extended with binders from a given pattern+    - `assertDistinctPattern` — establish that extended scope is distinct (if outer scope is)+    - `assertDistinctExt` — establish that extended scope is distinct and indeed an extension++  - Implement unification for patterns in `unifyPatterns`.+    This turns out to be one of the most difficult places, especially for compound patterns.+    Implementing patterns properly on the user side not comfortable at all!+    Luckily, we provide useful helpers like `andThenUnifyPatterns` and `andThenUnifyNameBinders`,+    as well as Template Haskell support to derive `UnifiablePattern`.++  - Generalize Free Foil to support arbitrary patterns.++  - The `Foil` and `FreeFoilTH` implementations now make use of the generalized pattern support.+ # 0.0.3 — 2024-06-20  - Add α-equivalence checks and α-normalization (see [#12](https://github.com/fizruk/free-foil/pull/12)):
free-foil.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           free-foil-version:        0.0.3+version:        0.1.0 synopsis:       Efficient Type-Safe Capture-Avoiding Substitution for Free (Scoped Monads) description:    Please see the README on GitHub at <https://github.com/fizruk/free-foil#readme> category:       Parsing
src/Control/Monad/Foil.hs view
@@ -21,13 +21,19 @@   NameBinder,   emptyScope,   extendScope,+  extendScopePattern,   member,   nameOf,+  namesOfPattern,   nameId,   withFreshBinder,   withFresh,+  withFreshPattern,   withRefreshed,+  withRefreshedPattern,+  withRefreshedPattern',   unsinkName,+  unsinkNamePattern,   -- * Safe (co)sinking and renaming   Sinkable(..),   CoSinkable(..),@@ -46,6 +52,15 @@   -- * Unification of binders   UnifyNameBinders(..),   unifyNameBinders,+  andThenUnifyPatterns,+  andThenUnifyNameBinders,+  UnifiablePattern(..),+  UnifiableInPattern(..),+  NameBinders,+  emptyNameBinders,+  mergeNameBinders,+  -- ** Eliminating impossible unification+  V2, absurd2,   -- * Name maps   NameMap,   emptyNameMap,
src/Control/Monad/Foil/Internal.hs view
@@ -1,9 +1,11 @@ {-# LANGUAGE BlockArguments             #-} {-# LANGUAGE ConstraintKinds            #-} {-# LANGUAGE DataKinds                  #-}+{-# LANGUAGE EmptyCase                  #-} {-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GADTs                      #-} {-# LANGUAGE KindSignatures             #-}+{-# LANGUAGE LambdaCase                 #-} {-# LANGUAGE MultiParamTypeClasses      #-} {-# LANGUAGE QuantifiedConstraints      #-} {-# LANGUAGE RankNTypes                 #-}@@ -15,6 +17,7 @@ {-# LANGUAGE DerivingStrategies         #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# OPTIONS_GHC -Wno-redundant-constraints #-}+{-# LANGUAGE DefaultSignatures          #-} -- | 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.@@ -34,13 +37,13 @@ module Control.Monad.Foil.Internal where  import           Control.DeepSeq (NFData (..))+import           Data.Coerce     (coerce) import           Data.IntMap import qualified Data.IntMap     as IntMap import           Data.IntSet import qualified Data.IntSet     as IntSet import           Data.Kind       (Type) import           Unsafe.Coerce-import Data.Coerce (coerce)  -- * Safe types and operations @@ -58,6 +61,11 @@ newtype Name (n :: S) = UnsafeName RawName   deriving newtype (NFData, Eq, Ord, Show) +-- | Convert 'Name' into an identifier.+-- This may be useful for printing and debugging.+nameId :: Name l -> Id+nameId (UnsafeName i) = i+ -- | A name binder is a name that extends scope @n@ to a (larger) scope @l@. newtype NameBinder (n :: S) (l :: S) =   UnsafeNameBinder (Name l)@@ -67,6 +75,12 @@ emptyScope :: Scope VoidS emptyScope = UnsafeScope IntSet.empty +-- | A runtime check for potential name capture.+member :: Name l -> Scope n -> Bool+member (UnsafeName name) (UnsafeScope s) = rawMember name s++-- ** Extending scopes+ -- | \(O(\min(n,W))\). -- Extend a scope with one name (safely). -- Note that as long as the foil is used as intended,@@ -76,19 +90,68 @@ extendScope (UnsafeNameBinder (UnsafeName name)) (UnsafeScope scope) =   UnsafeScope (IntSet.insert name scope) --- | A runtime check for potential name capture.-member :: Name l -> Scope n -> Bool-member (UnsafeName name) (UnsafeScope s) = rawMember name s+-- | Extend scope with variables inside a pattern.+-- This is a more flexible version of 'extendScope'.+extendScopePattern+  :: (Distinct n, CoSinkable pattern)+  => pattern n l -> Scope n -> Scope l+extendScopePattern pat scope = withPattern+  (\_scope' binder k ->+    unsafeAssertFresh binder $ \binder' ->+      k (ExtendScope (extendScope binder)) binder')+  idExtendScope+  compExtendScope+  scope+  pat+  (\(ExtendScope extend) _ -> extend scope) +-- | Auxiliary data structure for scope extension. Used in 'extendScopePattern'.+newtype ExtendScope n l (o :: S) (o' :: S) = ExtendScope (Scope n -> Scope l)++-- | Identity scope extension (no extension).+idExtendScope :: ExtendScope n n o o'+idExtendScope = ExtendScope id++-- | Compose scope extensions.+compExtendScope+  :: ExtendScope n i o o'+  -> ExtendScope i l o' o''+  -> ExtendScope n l o o''+compExtendScope (ExtendScope f) (ExtendScope g)+  = ExtendScope (g . f)++-- ** Collecting new names+ -- | Extract name from a name binder. nameOf :: NameBinder n l -> Name l nameOf (UnsafeNameBinder name) = name --- | Convert 'Name' into an identifier.--- This may be useful for printing and debugging.-nameId :: Name l -> Id-nameId (UnsafeName i) = i+-- | Extract names from a pattern.+-- This is a more flexible version of 'namesOf'.+namesOfPattern+  :: forall pattern n l. (Distinct n, CoSinkable pattern) => pattern n l -> [Name l]+namesOfPattern pat = withPattern @_ @n+  (\_scope' binder k ->+    unsafeAssertFresh binder $ \binder' ->+      k (NamesOf [nameOf binder]) binder')+  idNamesOf compNamesOf (error "impossible") pat+  (\(NamesOf names) _ -> names) +-- | Auxiliary structure collecting names in scope @l@ that extend scope @n@.+-- Used in 'namesOfPattern'.+newtype NamesOf (n :: S) l (o :: S) (o' :: S) = NamesOf [Name l]++-- | Empty list of names in scope @n@.+idNamesOf :: NamesOf n n o o'+idNamesOf = NamesOf []++-- | Concatenation of names, resulting in a list of names in @l@ that extend scope @n@.+compNamesOf :: NamesOf n i o o' -> NamesOf i l o' o'' -> NamesOf n l o o''+compNamesOf (NamesOf xs) (NamesOf ys) =+  NamesOf (coerce xs ++ ys)++-- ** Refreshing binders+ -- | Allocate a fresh binder for a given scope. withFreshBinder   :: Scope n@@ -98,30 +161,87 @@   where     binder = UnsafeNameBinder (UnsafeName (rawFreshName scope)) --- | Evidence that scope @n@ contains distinct names.-data DistinctEvidence (n :: S) where-  Distinct :: Distinct n => DistinctEvidence n---- | Unsafely declare that scope @n@ is distinct.--- Used in 'unsafeAssertFresh'.-unsafeDistinct :: DistinctEvidence n-unsafeDistinct = unsafeCoerce (Distinct :: DistinctEvidence VoidS)---- | Evidence that scope @l@ extends scope @n@.-data ExtEvidence (n :: S) (l :: S) where-  Ext :: Ext n l => ExtEvidence n l---- | Unsafely declare that scope @l@ extends scope @n@.--- Used in 'unsafeAssertFresh'.-unsafeExt :: ExtEvidence n l-unsafeExt = unsafeCoerce (Ext :: ExtEvidence VoidS VoidS)- -- | Safely produce a fresh name binder with respect to a given scope. withFresh   :: Distinct n => Scope n   -> (forall l. DExt n l => NameBinder n l -> r) -> r withFresh scope cont = withFreshBinder scope (`unsafeAssertFresh` cont) +-- | Rename a given pattern into a fresh version of it to extend a given scope.+--+-- This is similar to 'withRefreshPattern', except here renaming always takes place.+withFreshPattern+  :: (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'. DExt o o' => (Substitution e n o -> Substitution e l o') -> pattern o o' -> r)+  -- ^ Continuation, accepting the refreshed pattern.+  -> r+withFreshPattern scope pattern cont = withPattern+  (\scope' binder f -> withFresh scope'+    (\binder' -> f (WithRefreshedPattern (\subst -> addRename (sink subst) binder (nameOf binder'))) binder'))+  idWithRefreshedPattern+  compWithRefreshedPattern+  scope+  pattern+  (\(WithRefreshedPattern f) pattern' -> cont f pattern')++-- | 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.+withRefreshed+  :: Distinct o+  => Scope o    -- ^ Ambient scope.+  -> Name i     -- ^ Name to refresh (if it clashes with the ambient scope).+  -> (forall o'. DExt o o' => NameBinder o o' -> r)+  -- ^ Continuation, accepting the refreshed name.+  -> r+withRefreshed scope@(UnsafeScope rawScope) name@(UnsafeName rawName) cont+  | IntSet.member rawName rawScope = withFresh scope cont+  | otherwise = unsafeAssertFresh (UnsafeNameBinder name) cont++-- | 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'.+withRefreshedPattern+  :: (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'. DExt o o' => (Substitution e n o -> Substitution e l o') -> pattern o o' -> r)+  -- ^ Continuation, accepting the refreshed pattern.+  -> r+withRefreshedPattern scope pattern cont = withPattern+  (\scope' binder f -> withRefreshed scope' (nameOf binder)+    (\binder' -> f (WithRefreshedPattern (\subst -> addRename (sink subst) binder (nameOf binder'))) binder'))+  idWithRefreshedPattern+  compWithRefreshedPattern+  scope+  pattern+  (\(WithRefreshedPattern f) pattern' -> cont f pattern')++-- | Refresh (if needed) bound variables introduced in a pattern.+--+-- This is a version of 'withRefreshedPattern' that uses functional renamings instead of 'Substitution'.+withRefreshedPattern'+  :: (CoSinkable pattern, Distinct o, InjectName e, Sinkable e)+  => Scope o+  -> pattern n l+  -> (forall o'. DExt o o' => ((Name n -> e o) -> Name l -> e o') -> pattern o o' -> r) -> r+withRefreshedPattern' scope pattern cont = withPattern+  (\scope' binder f -> withRefreshed scope' (nameOf binder)+    (\binder' ->+      let k subst name = case unsinkName binder name of+              Nothing    -> injectName (nameOf binder')+              Just name' -> sink (subst name')+       in f (WithRefreshedPattern' k) binder'))+  idWithRefreshedPattern'+  compWithRefreshedPattern'+  scope+  pattern+  (\(WithRefreshedPattern' f) pattern' -> cont f pattern')+ -- | Unsafely declare that a given name (binder) -- is already fresh in any scope @n'@. unsafeAssertFresh :: forall n l n' l' r. NameBinder n l@@ -131,28 +251,73 @@     Distinct -> case unsafeExt @n' @l' of       Ext -> cont (unsafeCoerce binder) +-- | Auxiliary structure to accumulate substitution extensions+-- produced when refreshing a pattern.+-- Used in 'withRefreshedPattern' and 'withFreshPattern'.+newtype WithRefreshedPattern e n l o o' = WithRefreshedPattern (Substitution e n o -> Substitution e l o')++-- | Trivial substitution (coercion via 'sink').+idWithRefreshedPattern :: (Sinkable e, DExt o o') => WithRefreshedPattern e n n o o'+idWithRefreshedPattern = WithRefreshedPattern sink++-- | Composition of substitution extensions.+compWithRefreshedPattern+  :: (DExt o o', DExt o' o'')+  => WithRefreshedPattern e n i o o'+  -> WithRefreshedPattern e i l o' o''+  -> WithRefreshedPattern e n l o o''+compWithRefreshedPattern (WithRefreshedPattern f) (WithRefreshedPattern g) =+  WithRefreshedPattern (g . f)++-- | Auxiliary structure to accumulate substitution extensions+-- produced when refreshing a pattern.+-- Similar to 'WithRefreshedPattern', except here substitutions are represented as functions.+-- Used in 'withRefreshedPattern''.+newtype WithRefreshedPattern' e n l (o :: S) (o' :: S) = WithRefreshedPattern' ((Name n -> e o) -> Name l -> e o')++-- | Trivial substitution extension (coercion via 'sink').+idWithRefreshedPattern' :: (Sinkable e, DExt o o') => WithRefreshedPattern' e n n o o'+idWithRefreshedPattern' = WithRefreshedPattern' (\f n -> sink (f n))++-- | Composition of substitution extensions.+compWithRefreshedPattern'+  :: (DExt o o', DExt o' o'')+  => WithRefreshedPattern' e n i o o'+  -> WithRefreshedPattern' e i l o' o''+  -> WithRefreshedPattern' e n l o o''+compWithRefreshedPattern' (WithRefreshedPattern' f) (WithRefreshedPattern' g) =+  WithRefreshedPattern' (g . f)++-- ** Extracting proofs from binders and patterns++-- | Evidence that scope @n@ contains distinct names.+data DistinctEvidence (n :: S) where+  Distinct :: Distinct n => DistinctEvidence n++-- | Evidence that scope @l@ extends scope @n@.+data ExtEvidence (n :: S) (l :: S) where+  Ext :: Ext n l => ExtEvidence n l+ -- | A distinct scope extended with a 'NameBinder' is also distinct.-assertDistinct :: Distinct n => NameBinder n l -> DistinctEvidence l+assertDistinct :: (Distinct n, CoSinkable pattern) => pattern n l -> DistinctEvidence l assertDistinct _ = unsafeDistinct  -- | A distinct scope extended with a 'NameBinder' is also distinct.-assertExt :: NameBinder n l -> ExtEvidence n l+assertExt :: CoSinkable pattern => pattern n l -> ExtEvidence n l assertExt _ = unsafeExt --- | 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.-withRefreshed-  :: Distinct o-  => Scope o    -- ^ Ambient scope.-  -> Name i     -- ^ Name to refresh (if it clashes with the ambient scope).-  -> (forall o'. DExt o o' => NameBinder o o' -> r)-  -- ^ Continuation, accepting the refreshed name.-  -> r-withRefreshed scope@(UnsafeScope rawScope) name@(UnsafeName rawName) cont-  | IntSet.member rawName rawScope = withFresh scope cont-  | otherwise = unsafeAssertFresh (UnsafeNameBinder name) cont+-- | Unsafely declare that scope @n@ is distinct.+-- Used in 'unsafeAssertFresh'.+unsafeDistinct :: DistinctEvidence n+unsafeDistinct = unsafeCoerce (Distinct :: DistinctEvidence VoidS) +-- | Unsafely declare that scope @l@ extends scope @n@.+-- Used in 'unsafeAssertFresh'.+unsafeExt :: ExtEvidence n l+unsafeExt = unsafeCoerce (Ext :: ExtEvidence VoidS VoidS)++-- ** Unsinking names+ -- | Try coercing the name back to the (smaller) scope, -- given a binder that extends that scope. unsinkName :: NameBinder n l -> Name l -> Maybe (Name n)@@ -160,37 +325,266 @@   | nameOf binder == name = Nothing   | otherwise = Just (UnsafeName raw) +-- | 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'.+unsinkNamePattern+  :: forall pattern n l. (Distinct n, CoSinkable pattern)+  => pattern n l -> Name l -> Maybe (Name n)+unsinkNamePattern pat = withPattern @_ @n+  (\_scope' binder k ->+      unsafeAssertFresh binder $ \binder' ->+        k (UnsinkName (unsinkName binder)) binder')+  idUnsinkName+  compUnsinkName+  (error "impossible")  -- scope is not used, but has to be provided in general+  pat+  (\(UnsinkName unsink) _ -> unsink)++-- | Auxiliary structure for unsinking names.+-- Used in 'unsinkNamePattern'.+newtype UnsinkName n l (o :: S) (o' :: S) = UnsinkName (Name l -> Maybe (Name n))++-- | Trivial unsinking. If no scope extension took place, any name is free (since it cannot be bound by anything).+idUnsinkName :: UnsinkName n n o o'+idUnsinkName = UnsinkName Just++-- | Composition of unsinking for nested binders/patterns.+compUnsinkName+  :: UnsinkName n i o o'+  -> UnsinkName i l o' o''+  -> UnsinkName n l o o''+compUnsinkName (UnsinkName f) (UnsinkName g)+  = UnsinkName (\name -> g name >>= f)+ -- * Unification of binders  -- | Unification result for two binders, -- extending some common scope to scopes @l@ and @r@ respectively. ----- Due to the implementation of the foil,-data UnifyNameBinders n l r where+-- Due to the implementation of the foil, we can often rename binders efficiently,+-- by renaming binders only in one of the two unified terms.+data UnifyNameBinders (pattern :: S -> S -> Type) n l r where   -- | Binders are the same, proving that type parameters @l@ and @r@   -- are in fact equivalent.-  SameNameBinders :: UnifyNameBinders n l l+  SameNameBinders+    :: NameBinders n l  -- ^ /Unordered/ set of binders in the unified pattern (from any of the original patterns).+    -> UnifyNameBinders pattern n l l   -- | It is possible to safely rename the left binder   -- to match the right one.-  RenameLeftNameBinder :: (NameBinder n l -> NameBinder n r) -> UnifyNameBinders n l r+  RenameLeftNameBinder+    :: NameBinders n r                    -- ^ /Unordered/ set of binders in the unified pattern (the binders from the right pattern).+    -> (NameBinder n l -> NameBinder n r) -- ^ Binder renaming for the left pattern.+    -> UnifyNameBinders pattern n l r   -- | It is possible to safely rename the right binder   -- to match the left one.-  RenameRightNameBinder :: (NameBinder n r -> NameBinder n l) -> UnifyNameBinders n l r+  RenameRightNameBinder+    :: NameBinders n l                    -- ^ /Unordered/ set of binders in the unified pattern (the binders from the left pattern).+    -> (NameBinder n r -> NameBinder n l) -- ^ Binder renaming for the right pattern.+    -> UnifyNameBinders pattern n l r+  -- | It is necessary to rename both binders.+  RenameBothBinders+    :: NameBinders n lr                     -- ^ /Unordered/ set of binders in the unified pattern+    -> (NameBinder n l -> NameBinder n lr)  -- ^ Binder renaming for the left pattern.+    -> (NameBinder n r -> NameBinder n lr)  -- ^ Binder renaming for the right pattern.+    -> UnifyNameBinders pattern n l r+  -- | Cannot unify to (sub)patterns.+  NotUnifiable :: UnifyNameBinders pattern n 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. unifyNameBinders-  :: forall i l r.-     NameBinder i l-  -> NameBinder i r-  -> UnifyNameBinders i l r-unifyNameBinders (UnsafeNameBinder (UnsafeName i1)) (UnsafeNameBinder (UnsafeName i2))-  | i1 == i2  = unsafeCoerce (SameNameBinders @l)  -- equal names extend scopes equally-  | i1 < i2   = RenameRightNameBinder $ \(UnsafeNameBinder (UnsafeName i'')) ->+  :: forall i l r pattern. Distinct i+  => NameBinder i l -- ^ Left pattern.+  -> NameBinder i r -- ^ Right pattern.+  -> UnifyNameBinders pattern i l r+unifyNameBinders l@(UnsafeNameBinder (UnsafeName i1)) r@(UnsafeNameBinder (UnsafeName i2))+  | i1 == i2  = case assertDistinct l of+      Distinct -> unsafeCoerce (SameNameBinders (nameBindersSingleton l))  -- equal names extend scopes equally+  | i1 < i2   = RenameRightNameBinder (nameBindersSingleton l) $ \(UnsafeNameBinder (UnsafeName i'')) ->       if i'' == i2 then UnsafeNameBinder (UnsafeName i1) else UnsafeNameBinder (UnsafeName i'')-  | otherwise = RenameLeftNameBinder $ \(UnsafeNameBinder (UnsafeName i')) ->+  | otherwise = RenameLeftNameBinder (nameBindersSingleton r) $ \(UnsafeNameBinder (UnsafeName i')) ->       if i'  == i1 then UnsafeNameBinder (UnsafeName i2) else UnsafeNameBinder (UnsafeName i') +-- | Unsafely merge results of unification for nested binders/patterns.+-- Used in 'andThenUnifyPatterns'.+unsafeMergeUnifyBinders :: UnifyNameBinders pattern a a' a'' -> UnifyNameBinders pattern a''' b' b'' -> UnifyNameBinders pattern a b' b''+unsafeMergeUnifyBinders = \case++  SameNameBinders x -> \case+    SameNameBinders y -> SameNameBinders (x `unsafeMergeNameBinders` y)+    RenameLeftNameBinder y f -> RenameLeftNameBinder (x `unsafeMergeNameBinders` y) (unsafeCoerce f)+    RenameRightNameBinder y g -> RenameRightNameBinder (x `unsafeMergeNameBinders` y) (unsafeCoerce g)+    RenameBothBinders y f g -> RenameBothBinders (x `unsafeMergeNameBinders` y) (unsafeCoerce f) (unsafeCoerce g)+    NotUnifiable -> NotUnifiable++  RenameLeftNameBinder x f -> \case+    SameNameBinders y -> RenameLeftNameBinder (x `unsafeMergeNameBinders` y) (unsafeCoerce f)+    RenameLeftNameBinder y g -> RenameLeftNameBinder (x `unsafeMergeNameBinders` y) (unsafeCoerce f . unsafeCoerce g)+    RenameRightNameBinder y g -> RenameBothBinders (x `unsafeMergeNameBinders` y) (unsafeCoerce f) (unsafeCoerce g)+    RenameBothBinders y f' g -> RenameBothBinders (x `unsafeMergeNameBinders` y) (unsafeCoerce f . unsafeCoerce f') (unsafeCoerce g)+    NotUnifiable -> NotUnifiable++  RenameRightNameBinder x g -> \case+    SameNameBinders y -> RenameRightNameBinder (x `unsafeMergeNameBinders` y) (unsafeCoerce g)+    RenameLeftNameBinder y f -> RenameBothBinders (x `unsafeMergeNameBinders` y) (unsafeCoerce f) (unsafeCoerce g)+    RenameRightNameBinder y g' -> RenameRightNameBinder (x `unsafeMergeNameBinders` y) (unsafeCoerce g . unsafeCoerce g')+    RenameBothBinders y f g' -> RenameBothBinders (x `unsafeMergeNameBinders` y) (unsafeCoerce f) (unsafeCoerce g . unsafeCoerce g')+    NotUnifiable -> NotUnifiable++  RenameBothBinders x f g -> \case+    SameNameBinders y -> RenameBothBinders (x `unsafeMergeNameBinders` y) (unsafeCoerce f) (unsafeCoerce g)+    RenameLeftNameBinder y f' -> RenameBothBinders (x `unsafeMergeNameBinders` y) (unsafeCoerce f . unsafeCoerce f') (unsafeCoerce g)+    RenameRightNameBinder y g' -> RenameBothBinders (x `unsafeMergeNameBinders` y) (unsafeCoerce f) (unsafeCoerce g . unsafeCoerce g')+    RenameBothBinders y f' g' -> RenameBothBinders (x `unsafeMergeNameBinders` y) (unsafeCoerce f . unsafeCoerce f') (unsafeCoerce g . unsafeCoerce g')+    NotUnifiable -> NotUnifiable++  NotUnifiable -> const (NotUnifiable)++-- | Chain unification of nested patterns.+andThenUnifyPatterns+  :: (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'+andThenUnifyPatterns u (l, r) = unsafeMergeUnifyBinders u (unifyPatterns (unsafeCoerce l) r)++-- | Chain unification of nested patterns with 'NameBinder's.+andThenUnifyNameBinders+  :: (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'+andThenUnifyNameBinders u (l, r) = unsafeMergeUnifyBinders u (unifyNameBinders (unsafeCoerce l) r)++-- | An /unordered/ collection of 'NameBinder's, that together extend scope @n@ to scope @l@.+--+-- For an ordered version see 'NameBinderList'.+newtype NameBinders (n :: S) (l :: S) = UnsafeNameBinders IntSet++-- | /Unsafely/ merge sets of binders (via set union).+unsafeMergeNameBinders :: NameBinders a b -> NameBinders c d -> NameBinders n l+unsafeMergeNameBinders (UnsafeNameBinders x) (UnsafeNameBinders y) = UnsafeNameBinders (x <> y)++-- | An empty set of binders keeps the scope as is.+emptyNameBinders :: NameBinders n n+emptyNameBinders = UnsafeNameBinders IntSet.empty++-- | Composition of sets of binders.+mergeNameBinders :: NameBinders n i -> NameBinders i l -> NameBinders n l+mergeNameBinders = unsafeMergeNameBinders++-- | A singleton name binder set.+nameBindersSingleton :: NameBinder n l -> NameBinders n l+nameBindersSingleton binder = UnsafeNameBinders (IntSet.singleton (nameId (nameOf binder)))++-- | An /ordered/ collection (list) of 'NameBinder's, that together extend scope @n@ to scope @l@.+--+-- For an unordered version see 'NameBinders'.+data NameBinderList n l where+  -- | An empty list of binders keeps the scope as is.+  NameBinderListEmpty :: NameBinderList n n+  -- | A non-empty list of binders.+  NameBinderListCons+    :: NameBinder n i       -- ^ Outermost binder.+    -> NameBinderList i l   -- ^ Remaining list of binders.+    -> NameBinderList n l++-- | Convert an unordered set of name binders into an ordered list (with some order).+nameBindersList :: NameBinders n l -> NameBinderList n l+nameBindersList (UnsafeNameBinders names) = go (IntSet.toList names)+  where+    go []     = unsafeCoerce NameBinderListEmpty+    go (x:xs) = NameBinderListCons (UnsafeNameBinder (UnsafeName x)) (go xs)++-- | Convert an ordered list of name binders into an unordered set.+fromNameBindersList :: NameBinderList n l -> NameBinders n l+fromNameBindersList = UnsafeNameBinders . IntSet.fromList . go+  where+    go :: NameBinderList n l -> [RawName]+    go NameBinderListEmpty                 = []+    go (NameBinderListCons binder binders) = nameId (nameOf binder) : go binders++instance CoSinkable NameBinders where+  coSinkabilityProof _rename (UnsafeNameBinders names) cont =+    cont unsafeCoerce (UnsafeNameBinders names)++  withPattern withBinder unit comp scope binders cont =+    withPattern withBinder unit comp scope (nameBindersList binders) $ \f binders' ->+      cont f (fromNameBindersList binders')++instance CoSinkable NameBinderList where+  coSinkabilityProof rename NameBinderListEmpty cont = cont rename NameBinderListEmpty+  coSinkabilityProof rename (NameBinderListCons binder binders) cont =+    coSinkabilityProof rename binder $ \rename' binder' ->+      coSinkabilityProof rename' binders $ \rename'' binders' ->+        cont rename'' (NameBinderListCons binder' binders')++  withPattern withBinder unit comp scope binders cont = case binders of+    NameBinderListEmpty -> cont unit NameBinderListEmpty+    NameBinderListCons x xs ->+      withBinder scope x $ \f x' ->+        let scope' = extendScopePattern x' scope+        in withPattern withBinder unit comp scope' xs $ \f' xs' ->+            cont (comp f f') (NameBinderListCons x' xs')++-- ** Pattern combinators++-- | An empty pattern type specifies zero possibilities for patterns.+--+-- This type can be used to specify that patterns are not possible.+data V2 (n :: S) (l :: S)++-- | Since 'V2' values logically don't exist, this witnesses the logical reasoning tool of "ex falso quodlibet".+absurd2 :: V2 n l -> a+absurd2 v2 = case v2 of {}++instance CoSinkable V2 where+  coSinkabilityProof _ v2 _ = absurd2 v2+  withPattern _ _ _ _ v2 _ = absurd2 v2+instance UnifiablePattern V2 where+  unifyPatterns = absurd2++-- | A unit pattern type corresponds to a wildcard pattern.+data U2 (n :: S) (l :: S) where+  U2 :: U2 n n  -- ^ Wildcard patten does not modify the scope.++instance CoSinkable U2 where+  coSinkabilityProof rename U2 cont = cont rename U2+  withPattern _withBinder unit _combine _scope U2 cont = cont unit U2+instance UnifiablePattern U2 where+  unifyPatterns U2 U2 = SameNameBinders emptyNameBinders++-- ** Unifiable patterns++-- | A pattern type is unifiable if it is possible to match two+-- patterns and decide how to rename binders.+class CoSinkable pattern => UnifiablePattern pattern where+  -- | Unify two patterns and decide which binders need to be renamed.+  unifyPatterns :: Distinct n => pattern n l -> pattern n r -> UnifyNameBinders pattern n l r++-- | 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).+class UnifiableInPattern a where+  -- | Unify non-binding components of a pattern.+  unifyInPattern :: a -> a -> Bool+  default unifyInPattern :: Eq a => a -> a -> Bool+  unifyInPattern = (==)++instance UnifiablePattern NameBinder where+  unifyPatterns = unifyNameBinders++-- | 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.+unsafeEqPattern :: (UnifiablePattern pattern, Distinct n) => pattern n l -> pattern n' l' -> Bool+unsafeEqPattern l r =+  case unifyPatterns l (unsafeCoerce r) of+    SameNameBinders{} -> True+    _                 -> False+ -- * Safe sinking  -- | Sinking an expression from scope @n@ into a (usualy extended) scope @l@,@@ -295,9 +689,30 @@     -- and a (possibly refreshed) pattern that extends @n'@ to @l'@.     -> r +  -- | Generalized processing of a pattern.+  --+  -- You can see 'withPattern' as a CPS-style traversal over the binders in a pattern.+  withPattern+    :: Distinct o+    => (forall x y z r'. Distinct z => Scope z -> NameBinder x y -> (forall z'. 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 z z'. 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 y y' z z' z''. (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'. DExt o o' => f n l o o' -> pattern o o' -> r)+    -- ^ Continuation, accepting result for the entire pattern and a (possibly refreshed) pattern.+    -> r+ instance CoSinkable NameBinder where   coSinkabilityProof _rename (UnsafeNameBinder name) cont =     cont unsafeCoerce (UnsafeNameBinder name)++  withPattern f _ _ = f  -- * Safe substitions 
src/Control/Monad/Foil/TH/MkFoilData.hs view
@@ -3,9 +3,10 @@ {-# LANGUAGE TemplateHaskellQuotes #-} {-# OPTIONS_GHC -Wno-incomplete-patterns #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}-module Control.Monad.Foil.TH.MkFoilData (mkFoilData) where+module Control.Monad.Foil.TH.MkFoilData where  import           Language.Haskell.TH+import Language.Haskell.TH.Syntax (addModFinalizer)  import qualified Control.Monad.Foil.Internal as Foil import Control.Monad.Foil.TH.Util@@ -20,24 +21,72 @@ mkFoilData termT nameT scopeT patternT = do   n <- newName "n"   l <- newName "l"-  TyConI (DataD _ctx _name patternTVars _kind patternCons _deriv) <- reify patternT   TyConI (DataD _ctx _name scopeTVars _kind scopeCons _deriv) <- reify scopeT   TyConI (DataD _ctx _name termTVars _kind termCons _deriv) <- reify termT -  foilPatternCons <- mapM (toPatternCon patternTVars n) patternCons   let foilScopeCons = map (toScopeCon scopeTVars n) scopeCons   let foilTermCons = map (toTermCon termTVars n l) termCons -  return+  patternD <- mkFoilPattern nameT patternT+  addModFinalizer $ putDoc (DeclDoc foilTermT)+    ("/Generated/ with '" ++ show 'mkFoilData ++ "'. A scope-safe version of '" ++ show termT ++ "'.")+  addModFinalizer $ putDoc (DeclDoc foilScopeT)+    ("/Generated/ with '" ++ show 'mkFoilData ++ "'. A scope-safe version of '" ++ show scopeT ++ "'.")+  return $     [ DataD [] foilTermT (termTVars ++ [KindedTV n BndrReq (PromotedT ''Foil.S)]) Nothing foilTermCons []     , DataD [] foilScopeT (scopeTVars ++ [KindedTV n BndrReq (PromotedT ''Foil.S)]) Nothing foilScopeCons []-    , DataD [] foilPatternT (patternTVars ++ [KindedTV n BndrReq (PromotedT ''Foil.S), KindedTV l BndrReq (PromotedT ''Foil.S)]) Nothing foilPatternCons []-    ]+    ] ++ patternD   where     foilTermT = mkName ("Foil" ++ nameBase termT)     foilScopeT = mkName ("Foil" ++ nameBase scopeT)     foilPatternT = mkName ("Foil" ++ nameBase patternT) +    -- | Convert a constructor declaration for a raw scoped term+    -- into a constructor for the scope-safe scoped term.+    toScopeCon :: [TyVarBndr BndrVis] -> Name -> Con -> Con+    toScopeCon _tvars n (NormalC conName params) =+      NormalC foilConName (map toScopeParam params)+      where+        foilConName = mkName ("Foil" ++ nameBase conName)+        toScopeParam (_bang, PeelConT tyName tyParams)+          | tyName == termT = (_bang, PeelConT foilTermT (tyParams ++ [VarT n]))+        toScopeParam _bangType = _bangType++    -- | Convert a constructor declaration for a raw term+    -- into a constructor for the scope-safe term.+    toTermCon :: [TyVarBndr BndrVis] -> Name -> Name -> Con -> Con+    toTermCon tvars n l (NormalC conName params) =+      GadtC [foilConName] (map toTermParam params) (PeelConT foilTermT (map (VarT . tvarName) tvars ++ [VarT n]))+      where+        foilNames = [n, l]+        foilConName = mkName ("Foil" ++ nameBase conName)+        toTermParam (_bang, PeelConT tyName tyParams)+          | tyName == patternT = (_bang, PeelConT foilPatternT (tyParams ++ map VarT foilNames))+          | tyName == nameT = (_bang, AppT (ConT ''Foil.Name) (VarT n))+          | tyName == scopeT = (_bang, PeelConT foilScopeT (tyParams ++ [VarT l]))+          | tyName == termT = (_bang, PeelConT foilTermT (tyParams ++ [VarT n]))+        toTermParam _bangType = _bangType++-- | Generate just the scope-safe patterns.+mkFoilPattern+  :: Name -- ^ Type name for raw variable identifiers.+  -> Name -- ^ Type name for raw patterns.+  -> Q [Dec]+mkFoilPattern nameT patternT = do+  n <- newName "n"+  l <- newName "l"+  TyConI (DataD _ctx _name patternTVars _kind patternCons _deriv) <- reify patternT++  foilPatternCons <- mapM (toPatternCon patternTVars n) patternCons++  addModFinalizer $ putDoc (DeclDoc foilPatternT)+    ("/Generated/ with '" ++ show 'mkFoilPattern ++ "'. A scope-safe version of '" ++ show patternT ++ "'.")+  return+    [ DataD [] foilPatternT (patternTVars ++ [KindedTV n BndrReq (PromotedT ''Foil.S), KindedTV l BndrReq (PromotedT ''Foil.S)]) Nothing foilPatternCons []+    ]+  where+    foilPatternT = mkName ("Foil" ++ nameBase patternT)+     -- | Convert a constructor declaration for a raw pattern type     -- into a constructor for the scope-safe pattern type.     toPatternCon@@ -48,6 +97,7 @@     toPatternCon tvars n (NormalC conName params) = do       (lastScopeName, foilParams) <- toPatternConParams 1 n params       let foilConName = mkName ("Foil" ++ nameBase conName)+      addModFinalizer $ putDoc (DeclDoc foilConName) ("Corresponds to '" ++ show conName ++ "'.")       return (GadtC [foilConName] foilParams (PeelConT foilPatternT (map (VarT . tvarName) tvars ++ [VarT n, VarT lastScopeName])))       where         -- | Process type parameters of a pattern,@@ -79,29 +129,3 @@             _ -> do               (l, conParams') <- toPatternConParams (i+1) p conParams               return (l, param : conParams')--    -- | Convert a constructor declaration for a raw scoped term-    -- into a constructor for the scope-safe scoped term.-    toScopeCon :: [TyVarBndr BndrVis] -> Name -> Con -> Con-    toScopeCon _tvars n (NormalC conName params) =-      NormalC foilConName (map toScopeParam params)-      where-        foilConName = mkName ("Foil" ++ nameBase conName)-        toScopeParam (_bang, PeelConT tyName tyParams)-          | tyName == termT = (_bang, PeelConT foilTermT (tyParams ++ [VarT n]))-        toScopeParam _bangType = _bangType--    -- | Convert a constructor declaration for a raw term-    -- into a constructor for the scope-safe term.-    toTermCon :: [TyVarBndr BndrVis] -> Name -> Name -> Con -> Con-    toTermCon tvars n l (NormalC conName params) =-      GadtC [foilConName] (map toTermParam params) (PeelConT foilTermT (map (VarT . tvarName) tvars ++ [VarT n]))-      where-        foilNames = [n, l]-        foilConName = mkName ("Foil" ++ nameBase conName)-        toTermParam (_bang, PeelConT tyName tyParams)-          | tyName == patternT = (_bang, PeelConT foilPatternT (tyParams ++ map VarT foilNames))-          | tyName == nameT = (_bang, AppT (ConT ''Foil.Name) (VarT n))-          | tyName == scopeT = (_bang, PeelConT foilScopeT (tyParams ++ [VarT l]))-          | tyName == termT = (_bang, PeelConT foilTermT (tyParams ++ [VarT n]))-        toTermParam _bangType = _bangType
src/Control/Monad/Foil/TH/MkFromFoil.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE RankNTypes            #-} {-# LANGUAGE QuasiQuotes           #-} {-# LANGUAGE TemplateHaskellQuotes #-}-module Control.Monad.Foil.TH.MkFromFoil (mkFromFoil) where+module Control.Monad.Foil.TH.MkFromFoil where  import           Language.Haskell.TH import Language.Haskell.TH.Syntax (addModFinalizer)@@ -57,12 +57,12 @@           -> $rtype         |] -  addModFinalizer $ putDoc (DeclDoc fromFoilTermT)-    "Convert a scope-safe term into a raw term."-  addModFinalizer $ putDoc (DeclDoc fromFoilPatternT)-    "Convert a scope-safe pattern into a raw pattern."-  addModFinalizer $ putDoc (DeclDoc fromFoilScopedT)-    "Convert a scope-safe scoped term into a raw scoped term."+  addModFinalizer $ putDoc (DeclDoc fromFoilTermT) $+    "/Generated/ with '" ++ show 'mkFromFoil ++ "'. Convert a scope-safe term into a raw term."+  addModFinalizer $ putDoc (DeclDoc fromFoilPatternT) $+    "/Generated/ with '" ++ show 'mkFromFoil ++ "'. Convert a scope-safe pattern into a raw pattern."+  addModFinalizer $ putDoc (DeclDoc fromFoilScopedT) $+    "/Generated/ with '" ++ show 'mkFromFoil ++ "'. Convert a scope-safe scoped term into a raw scoped term."    return     [ fromFoilTermSignature@@ -225,6 +225,78 @@              mkConParamVar :: BangType -> Int -> Name             mkConParamVar _ty i = mkName ("x" <> show i)+        toMatch RecC{} = error "Record constructors (RecC) are not supported yet!"+        toMatch InfixC{} = error "Infix constructors (InfixC) are not supported yet!"+        toMatch ForallC{} = error "Existential constructors (ForallC) are not supported yet!"+        toMatch GadtC{} = error "GADT constructors (GadtC) are not supported yet!"+        toMatch RecGadtC{} = error "Record GADT constructors (RecGadtC) are not supported yet!"++-- | Generate conversion function from raw to scope-safe pattern.+mkFromFoilPattern+  :: Name -- ^ Type name for raw variable identifiers.+  -> Name -- ^ Type name for raw patterns.+  -> Q [Dec]+mkFromFoilPattern nameT patternT = do+  n <- newName "n"+  let ntype = return (VarT n)+  l <- newName "l"+  let ltype = return (VarT l)+  TyConI (DataD _ctx _name patternTVars _kind patternCons _deriv) <- reify patternT++  let patternParams = map (VarT . tvarName) patternTVars++  fromFoilPatternSignature <-+    SigD fromFoilPatternT <$>+      [t| (Int -> $(return (ConT nameT)))+          -> $(return (PeelConT foilPatternT patternParams)) $ntype $ltype+          -> $(return (PeelConT patternT patternParams))+        |]++  addModFinalizer $ putDoc (DeclDoc fromFoilPatternT) $+    "/Generated/ with '" ++ show 'mkFromFoilPattern ++ "'. Convert a scope-safe pattern into a raw pattern."++  return+    [ fromFoilPatternSignature+    , fromFoilPatternBody patternCons+    ]+  where+    foilPatternT = mkName ("Foil" ++ nameBase patternT)++    fromFoilPatternT = mkName ("fromFoil" ++ nameBase patternT)++    fromFoilPatternBody patternCons = FunD fromFoilPatternT+      [Clause [VarP toRawIdent, VarP pattern] (NormalB (CaseE (VarE pattern) (map toMatch patternCons))) []]+      where+        toRawIdent = mkName "toRawIdent"+        pattern = mkName "pattern"++        toMatch (NormalC conName params) =+          Match (ConP foilConName [] conParamPatterns) (NormalB conMatchBody) []+          where+            conMatchBody = go 1 (ConE conName) params++            go _i p [] = p+            go i p ((_bang, PeelConT tyName _tyParams) : conParams)+              | tyName == nameT = go (i + 1)+                  (AppE p (AppE (VarE toRawIdent) (AppE (VarE 'Foil.nameId) (AppE (VarE 'Foil.nameOf) (VarE xi)))))+                  conParams+              | tyName == patternT = go (i+1)+                  (AppE p (foldl AppE (VarE fromFoilPatternT) [VarE toRawIdent, VarE xi]))+                  conParams+              where+                xi = mkName ("x" <> show i)+            go i p (_ : conParams) =+              go (i + 1) (AppE p (VarE xi)) conParams+              where+                xi = mkName ("x" <> show i)++            foilConName = mkName ("Foil" ++ nameBase conName)+            conParamPatterns = map VarP conParamVars++            conParamVars = zipWith mkConParamVar params [1..]++            mkConParamVar :: BangType -> Int -> Name+            mkConParamVar _ i = mkName ("x" <> show i)         toMatch RecC{} = error "Record constructors (RecC) are not supported yet!"         toMatch InfixC{} = error "Infix constructors (InfixC) are not supported yet!"         toMatch ForallC{} = error "Existential constructors (ForallC) are not supported yet!"
src/Control/Monad/Foil/TH/MkInstancesFoil.hs view
@@ -3,12 +3,13 @@ {-# LANGUAGE QuasiQuotes           #-} {-# LANGUAGE TemplateHaskellQuotes #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-}-module Control.Monad.Foil.TH.MkInstancesFoil (mkInstancesFoil) where+module Control.Monad.Foil.TH.MkInstancesFoil where  import           Language.Haskell.TH -import qualified Control.Monad.Foil  as Foil-import Control.Monad.Foil.TH.Util+import qualified Control.Monad.Foil         as Foil+import           Control.Monad.Foil.TH.Util+import           Data.List                  (nub)  -- | Generate 'Foil.Sinkable' and 'Foil.CoSinkable' instances. mkInstancesFoil@@ -18,25 +19,22 @@   -> Name -- ^ Type name for raw patterns.   -> Q [Dec] mkInstancesFoil termT nameT scopeT patternT = do-  TyConI (DataD _ctx _name patternTVars _kind patternCons _deriv) <- reify patternT   TyConI (DataD _ctx _name scopeTVars _kind scopeCons _deriv) <- reify scopeT   TyConI (DataD _ctx _name termTVars _kind termCons _deriv) <- reify termT -  return+  coSinkablePatternD <- deriveCoSinkable nameT patternT++  return $     [ InstanceD Nothing [] (AppT (ConT ''Foil.Sinkable) (PeelConT foilScopeT (map (VarT . tvarName) scopeTVars)))         [ FunD 'Foil.sinkabilityProof (map clauseScopedTerm scopeCons) ] -    , InstanceD Nothing [] (AppT (ConT ''Foil.CoSinkable) (PeelConT foilPatternT (map (VarT . tvarName) patternTVars)))-        [ FunD 'Foil.coSinkabilityProof (map clausePattern patternCons) ]-     , InstanceD Nothing [] (AppT (ConT ''Foil.Sinkable) (PeelConT foilTermT (map (VarT . tvarName) termTVars)))         [ FunD 'Foil.sinkabilityProof (map clauseTerm termCons)]-    ]+    ] ++ coSinkablePatternD    where     foilTermT = mkName ("Foil" ++ nameBase termT)     foilScopeT = mkName ("Foil" ++ nameBase scopeT)-    foilPatternT = mkName ("Foil" ++ nameBase patternT)      clauseScopedTerm :: Con -> Clause     clauseScopedTerm = clauseTerm@@ -54,7 +52,7 @@         []       where         foilConName = mkName ("Foil" ++ nameBase conName)-        rename = mkName "rename"+        rename = mkName "_rename"         conParamPatterns = zipWith mkConParamPattern params [1..]         mkConParamPattern _ i = VarP (mkName ("x" ++ show i)) @@ -80,6 +78,23 @@           where             xi = mkName ("x" ++ show i) +-- | Generate 'Foil.Sinkable' and 'Foil.CoSinkable' instances.+deriveCoSinkable+  :: Name -- ^ Type name for raw variable identifiers.+  -> Name -- ^ Type name for raw patterns.+  -> Q [Dec]+deriveCoSinkable nameT patternT = do+  TyConI (DataD _ctx _name patternTVars _kind patternCons _deriv) <- reify patternT++  return+    [ InstanceD Nothing [] (AppT (ConT ''Foil.CoSinkable) (PeelConT foilPatternT (map (VarT . tvarName) patternTVars)))+        [ FunD 'Foil.coSinkabilityProof (map clausePattern patternCons)+        , FunD 'Foil.withPattern (map clauseWithPattern patternCons) ]+    ]++  where+    foilPatternT = mkName ("Foil" ++ nameBase patternT)+     clausePattern :: Con -> Clause     clausePattern RecC{} = error "Record constructors (RecC) are not supported yet!"     clausePattern InfixC{} = error "Infix constructors (InfixC) are not supported yet!"@@ -113,3 +128,118 @@           go (i + 1) rename' (AppE p (VarE xi)) conPatterns           where             xi = mkName ("x" ++ show i)++    clauseWithPattern :: Con -> Clause+    clauseWithPattern RecC{} = error "Record constructors (RecC) are not supported yet!"+    clauseWithPattern InfixC{} = error "Infix constructors (InfixC) are not supported yet!"+    clauseWithPattern ForallC{} = error "Existential constructors (ForallC) are not supported yet!"+    clauseWithPattern GadtC{} = error "GADT constructors (GadtC) are not supported yet!"+    clauseWithPattern RecGadtC{} = error "Record GADT constructors (RecGadtC) are not supported yet!"+    clauseWithPattern (NormalC conName params) =+      Clause+        [VarP withNameBinder, VarP id', VarP comp, VarP scope, ConP foilConName [] conParamPatterns, VarP cont]+        (NormalB (go 1 scope (VarE id') (ConE foilConName) params))+        []+      where+        foilConName = mkName ("Foil" ++ nameBase conName)+        withNameBinder = mkName "_withNameBinder"+        id' = mkName "id'"+        comp = mkName "_comp"+        scope = mkName "_scope"+        cont = mkName "cont"+        conParamPatterns = zipWith mkConParamPattern params [1..]+        mkConParamPattern _ i = VarP (mkName ("x" ++ show i))++        go _i _scope' rename' p [] = AppE (AppE (VarE cont) rename') p+        go i scope' rename' p ((_bang, PeelConT tyName _tyParams) : conParams)+          | tyName == nameT || tyName == patternT =+              AppE+                (foldl AppE (VarE 'Foil.withPattern) [VarE withNameBinder, VarE id', VarE comp, VarE scope', VarE xi])+                (LamE [VarP renamei, VarP xi']+                  (LetE [ValD (VarP scopei) (NormalB (AppE (AppE (VarE 'Foil.extendScopePattern) (VarE xi')) (VarE scope'))) []]+                    (go (i + 1) scopei (foldl AppE (VarE comp) [rename', VarE renamei]) (AppE p (VarE xi')) conParams)))+          where+            xi = mkName ("x" ++ show i)+            xi' = mkName ("x" ++ show i ++ "'")+            renamei = mkName ("f" ++ show i)+            scopei = mkName ("_scope" ++ show i)+        go i scope' rename' p (_ : conPatterns) =+          go (i + 1) scope' rename' (AppE p (VarE xi)) conPatterns+          where+            xi = mkName ("x" ++ show i)++-- | Generate 'Foil.Sinkable' and 'Foil.CoSinkable' instances.+deriveUnifiablePattern+  :: Name -- ^ Type name for raw variable identifiers.+  -> Name -- ^ Type name for raw patterns.+  -> Q [Dec]+deriveUnifiablePattern nameT patternT = do+  TyConI (DataD _ctx _name patternTVars _kind patternCons _deriv) <- reify patternT++  let (eqTypes, clauses) = mapM clauseUnifyPatterns patternCons+      ctx = nub [ AppT (ConT ''Foil.UnifiableInPattern) type_ | type_ <- eqTypes, type_ `elem` map (VarT . tvarName) patternTVars ]+  return+    [ InstanceD Nothing ctx (AppT (ConT ''Foil.UnifiablePattern) (PeelConT foilPatternT (map (VarT . tvarName) patternTVars)))+        [ FunD 'Foil.unifyPatterns (clauses ++ [notUnifiableClause]) ]+    ]++  where+    foilPatternT = mkName ("Foil" ++ nameBase patternT)++    notUnifiableClause :: Clause+    notUnifiableClause = Clause [WildP, WildP] (NormalB (ConE 'Foil.NotUnifiable)) []++    clauseUnifyPatterns :: Con -> ([Type], Clause)+    clauseUnifyPatterns RecC{} = error "Record constructors (RecC) are not supported yet!"+    clauseUnifyPatterns InfixC{} = error "Infix constructors (InfixC) are not supported yet!"+    clauseUnifyPatterns ForallC{} = error "Existential constructors (ForallC) are not supported yet!"+    clauseUnifyPatterns GadtC{} = error "GADT constructors (GadtC) are not supported yet!"+    clauseUnifyPatterns RecGadtC{} = error "Record GADT constructors (RecGadtC) are not supported yet!"+    clauseUnifyPatterns (NormalC conName params) =+      case go 1 [] [] params of+        (body, eqTypes) ->+          (eqTypes, Clause+            [ConP foilConName [] paramsL, ConP foilConName [] paramsR]+            (NormalB body)+            [])+      where+        foilConName = mkName ("Foil" ++ nameBase conName)+        paramsL = zipWith (mkConParamPattern "l") params [1..]+        paramsR = zipWith (mkConParamPattern "r") params [1..]+        mkConParamPattern s _ i = VarP (mkName (s ++ show i))++        mkUnifyAllPairsRev [] = AppE (ConE 'Foil.SameNameBinders) (VarE 'Foil.emptyNameBinders)+        mkUnifyAllPairsRev [(isNameBinder, l, r)]+          | isNameBinder = AppE (AppE (VarE 'Foil.unifyNameBinders) l) r+          | otherwise    = AppE (AppE (VarE 'Foil.unifyPatterns) l) r+        mkUnifyAllPairsRev ((isNameBinder, l, r) : pairs) =+          InfixE+            (Just (mkUnifyAllPairsRev pairs))+            (VarE (if isNameBinder then 'Foil.andThenUnifyNameBinders else 'Foil.andThenUnifyPatterns))+            (Just (TupE [Just l, Just r]))+++        go _i eqTypes pairsRev [] = (mkUnifyAllPairsRev pairsRev, eqTypes)+        go i eqTypes pairsRev ((_bang, PeelConT tyName _tyParams) : conParams)+          | tyName == nameT || tyName == patternT =+            case go (i + 1) eqTypes ((isNameBinder, l, r) : pairsRev) conParams of+              (next, eqTypes') ->+                (CaseE (TupE [Just (AppE (VarE 'Foil.assertDistinct) l), Just (AppE (VarE 'Foil.assertDistinct) r)])+                  [Match+                    (TupP [ConP 'Foil.Distinct [] [], ConP 'Foil.Distinct [] []])+                    (NormalB next)+                    []], eqTypes')+          where+            isNameBinder = tyName == nameT+            l = VarE (mkName ("l" ++ show i))+            r = VarE (mkName ("r" ++ show i))+        go i eqTypes pairsRev ((_bang, type_) : conPatterns) =+          case go (i + 1) eqTypes pairsRev conPatterns of+            (next, eqTypes') ->+              (CondE+                (InfixE (Just l) (VarE 'Foil.unifyInPattern) (Just r))+                next+                (ConE 'Foil.NotUnifiable), type_ : eqTypes')+          where+            l = VarE (mkName ("l" ++ show i))+            r = VarE (mkName ("r" ++ show i))
src/Control/Monad/Foil/TH/MkToFoil.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE RankNTypes            #-} {-# LANGUAGE QuasiQuotes           #-} {-# LANGUAGE TemplateHaskellQuotes #-}-module Control.Monad.Foil.TH.MkToFoil (mkToFoil) where+module Control.Monad.Foil.TH.MkToFoil where  import           Language.Haskell.TH import Language.Haskell.TH.Syntax (addModFinalizer)@@ -55,8 +55,10 @@   idfun <- [e| id |]   extendScopeFun <- [e| Foil.extendScope |] -  addModFinalizer $ putDoc (DeclDoc extendScopePatternFunName)-    "Extend a scope with the names bound by the given pattern.\nThis is a more flexible version of 'Control.Monad.Foil.extendScope'."+  addModFinalizer $ putDoc (DeclDoc extendScopePatternFunName) $ unlines+    [ "/Generated/ with '" ++ show 'mkExtendScopeFoilPattern ++ "'."+    , "Extend a scope with the names bound by the given pattern."+    , "This is a more flexible version of '" ++ show 'Foil.extendScope ++ "'." ]    return     [ extendScopePatternSignature@@ -144,8 +146,10 @@   withRefreshedFun <- [e| Foil.withRefreshed |]   extendScopeFun <- [e| Foil.extendScope |] -  addModFinalizer $ putDoc (DeclDoc withRefreshedFoilPatternFunName)-    "Refresh (if needed) bound variables introduced in a pattern.\nThis is a more flexible version of 'Control.Monad.Foil.withRefreshed'."+  addModFinalizer $ putDoc (DeclDoc withRefreshedFoilPatternFunName) $ unlines+    [ "/Generated/ with '" ++ show 'mkWithRefreshedFoilPattern ++ "'."+    , "Refresh (if needed) bound variables introduced in a pattern."+    , "This is a more flexible version of '" ++ show 'Foil.withRefreshed ++ "'." ]    return     [ withRefreshedFoilPatternSignature@@ -189,7 +193,7 @@               where                 xi = mkName ("x" <> show i)                 xi' = mkName ("x" <> show i <> "'")-                scopei = mkName ("scope" <> show i)+                scopei = mkName ("_scope" <> show i)                 xsubst = mkName ("subst" <> show i)                 subst = mkName "subst"                 fi = LamE [VarP subst]@@ -258,12 +262,12 @@           -> $rtype         |] -  addModFinalizer $ putDoc (DeclDoc toFoilTermT)-    "Convert a raw term into a scope-safe term."-  addModFinalizer $ putDoc (DeclDoc toFoilPatternT)-    "Convert a raw pattern into a scope-safe pattern."-  addModFinalizer $ putDoc (DeclDoc toFoilScopedT)-    "Convert a raw scoped term into a scope-safe scoped term."+  addModFinalizer $ putDoc (DeclDoc toFoilTermT) $+    "/Generated/ with '" ++ show 'mkToFoilTerm ++ "'. Convert a raw term into a scope-safe term."+  addModFinalizer $ putDoc (DeclDoc toFoilPatternT) $+    "/Generated/ with '" ++ show 'mkToFoilTerm ++ "'. Convert a raw pattern into a scope-safe pattern."+  addModFinalizer $ putDoc (DeclDoc toFoilScopedT) $+    "/Generated/ with '" ++ show 'mkToFoilTerm ++ "'. Convert a raw scoped term into a scope-safe scoped term."    return     [ toFoilTermSignature@@ -295,7 +299,7 @@         toMatch (NormalC conName params) =           Match (ConP conName [] conParamPatterns) (NormalB conMatchBody) [toFoilVarD]           where-            toFoilVarFunName = mkName "lookupRawVar"+            toFoilVarFunName = mkName "_lookupRawVar"             toFoilVarFun = VarE toFoilVarFunName             x = mkName "x"             name = mkName "name"@@ -324,7 +328,7 @@               where                 xi = mkName ("x" <> show i)                 xi' = mkName ("x" <> show i <> "'")-                scopei = mkName ("scope" <> show i)+                scopei = mkName ("_scope" <> show i)                 envi = mkName ("env" <> show i)             go i scope' env' p (_ : conParams) =               go (i + 1) scope' env' (AppE p (VarE xi)) conParams@@ -366,7 +370,7 @@                             , ValD (VarP envi) (NormalB                                 (AppE (AppE (AppE (VarE 'Map.insert) (VarE xi))                                   (AppE (VarE 'Foil.nameOf) (VarE xi')))-                                  (InfixE (Just (VarE 'Foil.sink)) (VarE '(<$>)) (Just (VarE envi))))) []]+                                  (InfixE (Just (VarE 'Foil.sink)) (VarE '(<$>)) (Just env')))) []]                         (go (i+1) (VarE scopei) (VarE envi) (AppE p (VarE xi')) conParams)))               | tyName == patternT =                   AppE@@ -377,7 +381,7 @@               where                 xi = mkName ("x" <> show i)                 xi' = mkName ("x" <> show i <> "'")-                scopei = mkName ("scope" <> show i)+                scopei = mkName ("_scope" <> show i)                 envi = mkName ("env" <> show i)             go i scope' env' p (_ : conParams) =               go (i + 1) scope' env' (AppE p (VarE xi)) conParams@@ -407,7 +411,7 @@         toMatch (NormalC conName params) =           Match (ConP conName [] conParamPatterns) (NormalB conMatchBody) [toFoilVarD]           where-            toFoilVarFunName = mkName "lookupRawVar"+            toFoilVarFunName = mkName "_lookupRawVar"             toFoilVarFun = VarE toFoilVarFunName             x = mkName "x"             name = mkName "name"@@ -436,7 +440,7 @@               where                 xi = mkName ("x" <> show i)                 xi' = mkName ("x" <> show i <> "'")-                scopei = mkName ("scope" <> show i)+                scopei = mkName ("_scope" <> show i)                 envi = mkName ("env" <> show i)             go i scope' env' p (_ : conParams) =               go (i + 1) scope' env' (AppE p (VarE xi)) conParams@@ -451,6 +455,92 @@             mkConParamVar :: BangType -> Int -> Name             mkConParamVar _ty i = mkName ("x" <> show i) +        toMatch RecC{} = error "Record constructors (RecC) are not supported yet!"+        toMatch InfixC{} = error "Infix constructors (InfixC) are not supported yet!"+        toMatch ForallC{} = error "Existential constructors (ForallC) are not supported yet!"+        toMatch GadtC{} = error "GADT constructors (GadtC) are not supported yet!"+        toMatch RecGadtC{} = error "Record GADT constructors (RecGadtC) are not supported yet!"++-- | Generate a conversion function from raw terms to scope-safe terms.+mkToFoilPattern+  :: Name -- ^ Type name for raw variable identifiers.+  -> Name -- ^ Type name for raw patterns.+  -> Q [Dec]+mkToFoilPattern nameT patternT = do+  n <- newName "n"+  let ntype = return (VarT n)+  r <- newName "r"+  let rtype = return (VarT r)+  TyConI (DataD _ctx _name patternTVars _kind patternCons _deriv) <- reify patternT++  toFoilPatternSignature <-+    SigD toFoilPatternT <$>+      [t| Foil.Distinct $ntype+          => Foil.Scope $ntype+          -> Map $(return (ConT nameT)) (Foil.Name $ntype)+          -> $(return (PeelConT patternT (map (VarT . tvarName) patternTVars)))+          -> (forall l. Foil.DExt $ntype l => $(return (PeelConT foilPatternT (map (VarT . tvarName) patternTVars))) $ntype l -> Map $(return (ConT nameT)) (Foil.Name l) -> $rtype)+          -> $rtype+        |]++  addModFinalizer $ putDoc (DeclDoc toFoilPatternT) $+    "/Generated/ with '" ++ show 'mkToFoilPattern ++ "'. Convert a raw pattern into a scope-safe pattern."++  return+    [ toFoilPatternSignature+    , toFoilPatternBody patternCons+    ]+  where+    foilPatternT = mkName ("Foil" ++ nameBase patternT)+    toFoilPatternT = mkName ("toFoil" ++ nameBase patternT)++    toFoilPatternBody patternCons = FunD toFoilPatternT+      [Clause [VarP scope, VarP env, VarP pattern, VarP cont] (NormalB (CaseE (VarE pattern) (map toMatch patternCons))) []]+      where+        scope = mkName "scope"+        env = mkName "env"+        pattern = mkName "pattern"+        cont = mkName "cont"++        toMatch (NormalC conName params) =+          Match (ConP conName [] conParamPatterns) (NormalB conMatchBody) []+          where+            conMatchBody = go 1 (VarE scope) (VarE env) (ConE foilConName) params++            go _i _scope' env' p [] = AppE (AppE (VarE cont) p) env'+            go i scope' env' p ((_bang, PeelConT tyName _tyParams) : conParams)+              | tyName == nameT =+                  AppE (AppE (VarE 'Foil.withFresh) scope')+                    (LamE [VarP xi']+                      (LetE [ ValD (VarP scopei) (NormalB (AppE (AppE (VarE 'Foil.extendScope) (VarE xi')) scope')) []+                            , ValD (VarP envi) (NormalB+                                (AppE (AppE (AppE (VarE 'Map.insert) (VarE xi))+                                  (AppE (VarE 'Foil.nameOf) (VarE xi')))+                                  (InfixE (Just (VarE 'Foil.sink)) (VarE '(<$>)) (Just env')))) []]+                        (go (i+1) (VarE scopei) (VarE envi) (AppE p (VarE xi')) conParams)))+              | tyName == patternT =+                  AppE+                    (AppE (AppE (AppE (VarE toFoilPatternT) scope') env') (VarE xi))+                    (LamE [VarP xi', VarP envi]+                      (LetE [ValD (VarP scopei) (NormalB (AppE (AppE (VarE 'Foil.extendScopePattern) (VarE xi')) scope')) []]+                        (go (i+1) (VarE scopei) (VarE envi) (AppE p (VarE xi')) conParams)))+              where+                xi = mkName ("x" <> show i)+                xi' = mkName ("x" <> show i <> "'")+                scopei = mkName ("_scope" <> show i)+                envi = mkName ("env" <> show i)+            go i scope' env' p (_ : conParams) =+              go (i + 1) scope' env' (AppE p (VarE xi)) conParams+              where+                xi = mkName ("x" <> show i)++            foilConName = mkName ("Foil" ++ nameBase conName)+            conParamPatterns = map VarP conParamVars++            conParamVars = zipWith mkConParamVar params [1..]++            mkConParamVar :: BangType -> Int -> Name+            mkConParamVar _ i = mkName ("x" <> show i)         toMatch RecC{} = error "Record constructors (RecC) are not supported yet!"         toMatch InfixC{} = error "Infix constructors (InfixC) are not supported yet!"         toMatch ForallC{} = error "Existential constructors (ForallC) are not supported yet!"
src/Control/Monad/Free/Foil.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE DataKinds             #-}+{-# LANGUAGE RankNTypes             #-} {-# LANGUAGE DeriveAnyClass        #-} {-# LANGUAGE DeriveGeneric         #-} {-# LANGUAGE FlexibleContexts      #-}@@ -31,24 +32,25 @@ import           GHC.Generics                (Generic)  -- | Scoped term under a (single) name binder.-data ScopedAST sig n where-  ScopedAST :: Foil.NameBinder n l -> AST sig l -> ScopedAST sig n+data ScopedAST binder sig n where+  ScopedAST :: binder n l -> AST binder sig l -> ScopedAST binder sig n -instance (forall l. NFData (AST sig l)) => NFData (ScopedAST sig n) where+instance (forall x y. NFData (binder x y), forall l. NFData (AST binder sig l)) => NFData (ScopedAST binder sig n) where   rnf (ScopedAST binder body) = rnf binder `seq` rnf body  -- | A term, generated by a signature 'Bifunctor' @sig@, -- with (free) variables in scope @n@.-data AST sig n where+data AST binder sig n where   -- | A (free) variable in scope @n@.-  Var :: Foil.Name n -> AST sig n+  Var :: Foil.Name n -> AST binder sig n   -- | A non-variable syntactic construction specified by the signature 'Bifunctor' @sig@.-  Node :: sig (ScopedAST sig n) (AST sig n) -> AST sig n+  Node :: sig (ScopedAST binder sig n) (AST binder sig n) -> AST binder sig n -deriving instance Generic (AST sig n)-deriving instance (forall scope term. (NFData scope, NFData term) => NFData (sig scope term)) => NFData (AST sig n)+deriving instance Generic (AST binder sig n)+deriving instance (forall x y. NFData (binder x y), forall scope term. (NFData scope, NFData term) => NFData (sig scope term))+  => NFData (AST binder sig n) -instance Bifunctor sig => Foil.Sinkable (AST sig) where+instance (Bifunctor sig, Foil.CoSinkable binder) => Foil.Sinkable (AST binder sig) where   sinkabilityProof rename = \case     Var name -> Var (rename name)     Node node -> Node (bimap f (Foil.sinkabilityProof rename) node)@@ -57,26 +59,26 @@         Foil.extendRenaming rename binder $ \rename' binder' ->           ScopedAST binder' (Foil.sinkabilityProof rename' body) -instance Foil.InjectName (AST sig) where+instance Foil.InjectName (AST binder sig) where   injectName = Var  -- * Substitution  -- | Substitution for free (scoped monads). substitute-  :: (Bifunctor sig, Foil.Distinct o)+  :: (Bifunctor sig, Foil.Distinct o, Foil.CoSinkable binder)   => Foil.Scope o-  -> Foil.Substitution (AST sig) i o-  -> AST sig i-  -> AST sig o+  -> Foil.Substitution (AST binder sig) i o+  -> AST binder sig i+  -> AST binder sig o substitute scope subst = \case   Var name -> Foil.lookupSubst subst name   Node node -> Node (bimap f (substitute scope subst) node)   where     f (ScopedAST binder body) =-      Foil.withRefreshed scope (Foil.nameOf binder) $ \binder' ->-        let subst' = Foil.addRename (Foil.sink subst) binder (Foil.nameOf binder')-            scope' = Foil.extendScope binder' scope+      Foil.withRefreshedPattern scope binder $ \extendSubst binder' ->+        let subst' = extendSubst (Foil.sink subst)+            scope' = Foil.extendScopePattern binder' scope             body' = substitute scope' subst' body         in ScopedAST binder' body' @@ -89,24 +91,24 @@ -- -- In general, 'substitute' is more efficient since it does not always refresh binders. substituteRefreshed-  :: (Bifunctor sig, Foil.Distinct o)+  :: (Bifunctor sig, Foil.Distinct o, Foil.CoSinkable binder)   => Foil.Scope o-  -> Foil.Substitution (AST sig) i o-  -> AST sig i-  -> AST sig o+  -> Foil.Substitution (AST binder sig) i o+  -> AST binder sig i+  -> AST binder sig o substituteRefreshed scope subst = \case   Var name -> Foil.lookupSubst subst name   Node node -> Node (bimap f (substituteRefreshed scope subst) node)   where     f (ScopedAST binder body) =-      Foil.withFresh scope $ \binder' ->-        let subst' = Foil.addRename (Foil.sink subst) binder (Foil.nameOf binder')-            scope' = Foil.extendScope binder' scope+      Foil.withFreshPattern scope binder $ \extendSubst binder' ->+        let subst' = extendSubst (Foil.sink subst)+            scope' = Foil.extendScopePattern binder' scope             body' = substituteRefreshed scope' subst' body         in ScopedAST binder' body'  -- | @'AST' sig@ is a monad relative to 'Foil.Name'.-instance Bifunctor sig => Foil.RelMonad Foil.Name (AST sig) where+instance (Bifunctor sig, Foil.CoSinkable binder) => Foil.RelMonad Foil.Name (AST binder sig) where   rreturn = Var   rbind scope term subst =     case term of@@ -115,34 +117,32 @@     where       g x = Foil.rbind scope x subst       g' (ScopedAST binder body) =-        Foil.withRefreshed scope (Foil.nameOf binder) $ \binder' ->-          let scope' = Foil.extendScope binder' scope-              subst' name = case Foil.unsinkName binder name of-                          Nothing -> Foil.rreturn (Foil.nameOf binder')-                          Just n  -> Foil.sink (subst n)+        Foil.withRefreshedPattern' scope binder $ \extendSubst binder' ->+          let scope' = Foil.extendScopePattern binder' scope+              subst' = extendSubst subst            in ScopedAST binder' (Foil.rbind scope' body subst')  -- * \(\alpha\)-equivalence  -- | Refresh (force) all binders in a term, minimizing the used indices. refreshAST-  :: (Bifunctor sig, Foil.Distinct n)+  :: (Bifunctor sig, Foil.Distinct n, Foil.CoSinkable binder)   => Foil.Scope n-  -> AST sig n-  -> AST sig n+  -> AST binder sig n+  -> AST binder sig n refreshAST scope = \case   t@Var{} -> t   Node t -> Node (bimap (refreshScopedAST scope) (refreshAST scope) t)  -- | Similar to `refreshAST`, but for scoped terms.-refreshScopedAST :: (Bifunctor sig, Foil.Distinct n)+refreshScopedAST :: (Bifunctor sig, Foil.Distinct n, Foil.CoSinkable binder)   => Foil.Scope n-  -> ScopedAST sig n-  -> ScopedAST sig n+  -> ScopedAST binder sig n+  -> ScopedAST binder sig n refreshScopedAST scope (ScopedAST binder body) =-  Foil.withFresh scope $ \binder' ->-    let scope' = Foil.extendScope binder' scope-        subst = Foil.addRename (Foil.sink Foil.identitySubst) binder (Foil.nameOf binder')+  Foil.withFreshPattern scope binder $ \extendSubst binder' ->+    let scope' = Foil.extendScopePattern binder' scope+        subst = extendSubst (Foil.sink Foil.identitySubst)     in ScopedAST binder' (substituteRefreshed scope' subst body)  -- | \(\alpha\)-equivalence check for two terms in one scope@@ -151,10 +151,10 @@ -- Compared to 'alphaEquiv', this function may perform some unnecessary -- changes of bound variables when the binders are the same on both sides. alphaEquivRefreshed-  :: (Bifunctor sig, Bifoldable sig, ZipMatch sig, Foil.Distinct n)+  :: (Bifunctor sig, Bifoldable sig, ZipMatch sig, Foil.Distinct n, Foil.UnifiablePattern binder)   => Foil.Scope n-  -> AST sig n-  -> AST sig n+  -> AST binder sig n+  -> AST binder sig n   -> Bool alphaEquivRefreshed scope t1 t2 = refreshAST scope t1 `unsafeEqAST` refreshAST scope t2 @@ -164,10 +164,10 @@ -- Compared to 'alphaEquivRefreshed', this function might skip unnecessary -- changes of bound variables when both binders in two matching scoped terms coincide. alphaEquiv-  :: (Bifunctor sig, Bifoldable sig, ZipMatch sig, Foil.Distinct n)+  :: (Bifunctor sig, Bifoldable sig, ZipMatch sig, Foil.Distinct n, Foil.UnifiablePattern binder)   => Foil.Scope n-  -> AST sig n-  -> AST sig n+  -> AST binder sig n+  -> AST binder sig n   -> Bool alphaEquiv _scope (Var x) (Var y) = x == coerce y alphaEquiv scope (Node l) (Node r) =@@ -178,33 +178,43 @@  -- | Same as 'alphaEquiv' but for scoped terms. alphaEquivScoped-  :: (Bifunctor sig, Bifoldable sig, ZipMatch sig, Foil.Distinct n)+  :: (Bifunctor sig, Bifoldable sig, ZipMatch sig, Foil.Distinct n, Foil.UnifiablePattern binder)   => Foil.Scope n-  -> ScopedAST sig n-  -> ScopedAST sig n+  -> ScopedAST binder sig n+  -> ScopedAST binder sig n   -> Bool alphaEquivScoped scope   (ScopedAST binder1 body1)   (ScopedAST binder2 body2) =-    case Foil.unifyNameBinders binder1 binder2 of+    case Foil.unifyPatterns binder1 binder2 of       -- if binders are the same, then we can safely compare bodies-      Foil.SameNameBinders ->  -- after seeing this we know that body scopes are the same+      Foil.SameNameBinders{} ->  -- after seeing this we know that body scopes are the same         case Foil.assertDistinct binder1 of           Foil.Distinct ->-            let scope1 = Foil.extendScope binder1 scope+            let scope1 = Foil.extendScopePattern binder1 scope             in alphaEquiv scope1 body1 body2       -- if we can safely rename first binder into second-      Foil.RenameLeftNameBinder rename1to2 ->+      Foil.RenameLeftNameBinder _ rename1to2 ->         case Foil.assertDistinct binder2 of           Foil.Distinct ->-            let scope2 = Foil.extendScope binder2 scope+            let scope2 = Foil.extendScopePattern binder2 scope             in alphaEquiv scope2 (Foil.liftRM scope2 (Foil.fromNameBinderRenaming rename1to2) body1) body2       -- if we can safely rename second binder into first-      Foil.RenameRightNameBinder rename2to1 ->+      Foil.RenameRightNameBinder _ rename2to1 ->         case Foil.assertDistinct binder1 of           Foil.Distinct ->-            let scope1 = Foil.extendScope binder1 scope+            let scope1 = Foil.extendScopePattern binder1 scope             in alphaEquiv scope1 body1 (Foil.liftRM scope1 (Foil.fromNameBinderRenaming rename2to1) body2)+      -- if we need to rename both patterns+      Foil.RenameBothBinders binder' rename1 rename2 ->+        case Foil.assertDistinct binder' of+          Foil.Distinct ->+            let scope' = Foil.extendScopePattern binder' scope+            in alphaEquiv scope'+                (Foil.liftRM scope' (Foil.fromNameBinderRenaming rename1) body1)+                (Foil.liftRM scope' (Foil.fromNameBinderRenaming rename2) body2)+      -- if we cannot unify patterns then scopes are not alpha-equivalent+      Foil.NotUnifiable -> False  -- ** Unsafe equality checks @@ -213,9 +223,9 @@ -- scope extensions under binders (which might happen due to substitution -- under a binder in absence of name conflicts). unsafeEqAST-  :: (Bifoldable sig, ZipMatch sig)-  => AST sig n-  -> AST sig l+  :: (Bifoldable sig, ZipMatch sig, Foil.UnifiablePattern binder, Foil.Distinct n, Foil.Distinct l)+  => AST binder sig n+  -> AST binder sig l   -> Bool unsafeEqAST (Var x) (Var y) = x == coerce y unsafeEqAST (Node t1) (Node t2) =@@ -226,13 +236,14 @@  -- | A version of 'unsafeEqAST' for scoped terms. unsafeEqScopedAST-  :: (Bifoldable sig, ZipMatch sig)-  => ScopedAST sig n-  -> ScopedAST sig l+  :: (Bifoldable sig, ZipMatch sig, Foil.UnifiablePattern binder, Foil.Distinct n, Foil.Distinct l)+  => ScopedAST binder sig n+  -> ScopedAST binder sig l   -> Bool unsafeEqScopedAST (ScopedAST binder1 body1) (ScopedAST binder2 body2) = and-  [ binder1 == coerce binder2-  , body1 `unsafeEqAST` body2+  [ Foil.unsafeEqPattern binder1 binder2+  , case (Foil.assertDistinct binder1, Foil.assertDistinct binder2) of+      (Foil.Distinct, Foil.Distinct) -> body1 `unsafeEqAST` body2   ]  -- ** Syntactic matching (unification)@@ -253,14 +264,31 @@  -- ** Convert to free foil +-- | Convert a raw term into a scope-safe term. convertToAST-  :: (Foil.Distinct n, Bifunctor sig, Ord rawIdent)+  :: (Foil.Distinct n, Bifunctor sig, Ord rawIdent, Foil.CoSinkable binder)   => (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm))-  -> (rawPattern -> Maybe rawIdent)+  -- ^ Unpeel one syntax node (or a variable) from a raw term.+  -> (forall x z. Foil.Distinct x+      => Foil.Scope x+      -> Map rawIdent (Foil.Name x)+      -> rawPattern+      -> (forall y. Foil.DExt x y+          => binder x y+          -> Map rawIdent (Foil.Name y)+          -> z)+      -> z)+  -- ^ Convert raw pattern into a scope-safe pattern.   -> (rawScopedTerm -> rawTerm)+  -- ^ Extract a term from a scoped term (or crash).   -> Foil.Scope n-  -> Map rawIdent (Foil.Name n) -> rawTerm -> AST sig n-convertToAST toSig getPatternBinder getScopedTerm scope names t =+  -- ^ Resulting scope of the constructed term.+  -> Map rawIdent (Foil.Name n)+  -- ^ Known names of free variables in scope @n@.+  -> rawTerm+  -- ^ Raw term.+  -> AST binder sig n+convertToAST toSig fromRawPattern getScopedTerm scope names t =   case toSig t of     Left x ->       case Map.lookup x names of@@ -268,37 +296,57 @@         Just name -> Var name     Right node -> Node $       bimap-        (convertToScopedAST toSig getPatternBinder getScopedTerm scope names)-        (convertToAST toSig getPatternBinder getScopedTerm scope names)+        (convertToScopedAST toSig fromRawPattern getScopedTerm scope names)+        (convertToAST toSig fromRawPattern getScopedTerm scope names)         node +-- | Same as 'convertToAST' but for scoped terms. convertToScopedAST-  :: (Foil.Distinct n, Bifunctor sig, Ord rawIdent)+  :: (Foil.Distinct n, Bifunctor sig, Ord rawIdent, Foil.CoSinkable binder)   => (rawTerm -> Either rawIdent (sig (rawPattern, rawScopedTerm) rawTerm))-  -> (rawPattern -> Maybe rawIdent)+  -- ^ Unpeel one syntax node (or a variable) from a raw term.+  -> (forall x z. Foil.Distinct x+      => Foil.Scope x+      -> Map rawIdent (Foil.Name x)+      -> rawPattern+      -> (forall y. Foil.DExt x y+          => binder x y+          -> Map rawIdent (Foil.Name y)+          -> z)+      -> z)+  -- ^ Convert raw pattern into a scope-safe pattern.   -> (rawScopedTerm -> rawTerm)+  -- ^ Extract a term from a scoped term (or crash).   -> Foil.Scope n+  -- ^ Resulting scope of the constructed term.   -> Map rawIdent (Foil.Name n)+  -- ^ Known names of free variables in scope @n@.   -> (rawPattern, rawScopedTerm)-  -> ScopedAST sig n-convertToScopedAST toSig getPatternBinder getScopedTerm scope names (pat, scopedTerm) =-  Foil.withFresh scope $ \binder ->-    let scope' = Foil.extendScope binder scope-        names' =-          case getPatternBinder pat of-            Nothing -> Foil.sink <$> names-            Just x  -> Map.insert x (Foil.nameOf binder) (Foil.sink <$> names)-     in ScopedAST binder (convertToAST toSig getPatternBinder getScopedTerm scope' names' (getScopedTerm scopedTerm))+  -- ^ A pair of a pattern and a corresponding scoped term.+  -> ScopedAST binder sig n+convertToScopedAST toSig fromRawPattern getScopedTerm scope names (pat, scopedTerm) =+  fromRawPattern scope names pat $ \binder' names' ->+    let scope' = Foil.extendScopePattern binder' scope+     in ScopedAST binder' (convertToAST toSig fromRawPattern getScopedTerm scope' names' (getScopedTerm scopedTerm))  -- ** Convert from free foil +-- | Convert a scope-safe term back into a raw term. convertFromAST   :: Bifunctor sig   => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm)+  -- ^ Peel back one layer of syntax.   -> (rawIdent -> rawTerm)-  -> (rawIdent -> rawPattern)+  -- ^ Convert identifier into a raw variable term.+  -> (forall x y. (Int -> rawIdent) -> binder x y -> rawPattern)+  -- ^ Convert scope-safe pattern into a raw pattern.   -> (rawTerm -> rawScopedTerm)-  -> (Int -> rawIdent) -> AST sig n -> rawTerm+  -- ^ Wrap raw term into a scoped term.+  -> (Int -> rawIdent)+  -- ^ Convert underlying integer identifier of a bound variable into a raw identifier.+  -> AST binder sig n+  -- ^ Scope-safe term.+  -> rawTerm convertFromAST fromSig fromVar makePattern makeScoped f = \case   Var x -> fromVar (f (Foil.nameId x))   Node node -> fromSig $@@ -307,14 +355,23 @@       (convertFromAST fromSig fromVar makePattern makeScoped f)       node +-- | Same as 'convertFromAST' but for scoped terms. convertFromScopedAST   :: Bifunctor sig   => (sig (rawPattern, rawScopedTerm) rawTerm -> rawTerm)+  -- ^ Peel back one layer of syntax.   -> (rawIdent -> rawTerm)-  -> (rawIdent -> rawPattern)+  -- ^ Convert identifier into a raw variable term.+  -> (forall x y. (Int -> rawIdent) -> binder x y -> rawPattern)+  -- ^ Convert scope-safe pattern into a raw pattern.   -> (rawTerm -> rawScopedTerm)-  -> (Int -> rawIdent) -> ScopedAST sig n -> (rawPattern, rawScopedTerm)+  -- ^ Wrap raw term into a scoped term.+  -> (Int -> rawIdent)+  -- ^ Convert underlying integer identifier of a bound variable into a raw identifier.+  -> ScopedAST binder sig n+  -- ^ Scope-safe scoped term.+  -> (rawPattern, rawScopedTerm) convertFromScopedAST fromSig fromVar makePattern makeScoped f = \case   ScopedAST binder body ->-    ( makePattern (f (Foil.nameId (Foil.nameOf binder)))+    ( makePattern f binder     , makeScoped (convertFromAST fromSig fromVar makePattern makeScoped f body))
src/Control/Monad/Free/Foil/Example.hs view
@@ -25,15 +25,15 @@   deriving (Functor) deriveBifunctor ''ExprF -pattern AppE :: AST ExprF n -> AST ExprF n -> AST ExprF n+pattern AppE :: AST binder ExprF n -> AST binder ExprF n -> AST binder ExprF n pattern AppE x y = Node (AppF x y) -pattern LamE :: NameBinder n l -> AST ExprF l -> AST ExprF n+pattern LamE :: binder n l -> AST binder ExprF l -> AST binder ExprF n pattern LamE binder body = Node (LamF (ScopedAST binder body))  {-# COMPLETE Var, AppE, LamE #-} -type Expr = AST ExprF+type Expr = AST NameBinder ExprF  -- | Use 'ppExpr' to show \(\lambda\)-terms. instance Show (Expr n) where
src/Control/Monad/Free/Foil/TH/Convert.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE LambdaCase      #-} {-# OPTIONS_GHC -fno-warn-type-defaults      #-}+{-# LANGUAGE LambdaCase      #-} {-# LANGUAGE TemplateHaskell #-} module Control.Monad.Free.Foil.TH.Convert where @@ -61,7 +61,7 @@     [t| $termType -> Either $nameType ($signatureType ($patternType, $scopeType) $termType) |]    addModFinalizer $ putDoc (DeclDoc convertTermToSigT)-    ("/Generated/ with '" ++ show 'mkConvertToFreeFoil ++ "'. Perform one step of converting '" ++ show termT ++ "', peeling off one node of type '" ++ show signatureT ++ "'.")+    ("/Generated/ with '" ++ show 'mkConvertToSig ++ "'. Perform one step of converting '" ++ show termT ++ "', peeling off one node of type '" ++ show signatureT ++ "'.")   return     [ SigD convertTermToSigT convertTermToSigClausesType     , FunD convertTermToSigT convertTermToSigClauses@@ -77,11 +77,11 @@         where           x = mkName "x"           isVarP VarP{} = True-          isVarP _ = False+          isVarP _      = False           pats =             [ case type_ of                 PeelConT typeName _ | typeName == nameT -> VarP x-                _ -> WildP+                _                                       -> WildP             | (_bang, type_) <- types ]       NormalC conName types -> mkClause conName conName' types         where@@ -130,7 +130,7 @@     [t| $signatureType ($patternType, $scopeType) $termType -> $termType |]    addModFinalizer $ putDoc (DeclDoc convertTermFromSigT)-    ("/Generated/ with '" ++ show 'mkConvertToFreeFoil ++ "'. Perform one step of converting '" ++ show termT ++ "', peeling off one node of type '" ++ show signatureT ++ "'.")+    ("/Generated/ with '" ++ show 'mkConvertFromSig ++ "'. Perform one step of converting '" ++ show termT ++ "', peeling off one node of type '" ++ show signatureT ++ "'.")   return     [ SigD convertTermFromSigT convertTermFromSigClausesType     , FunD convertTermFromSigT convertTermFromSigClauses@@ -205,9 +205,9 @@     mkClause :: Name -> [BangType] -> Q [Clause]     mkClause conName types = do       body <- case concat vars of-        [] -> [e| Nothing |]+        []       -> [e| Nothing |]         [Just y] -> [e| Just $y |]-        _ -> [e| error "complex patterns are not supported" |]+        _        -> [e| error "complex patterns are not supported" |]       return [ Clause [ConP conName [] pats] (NormalB body) [] ]       where         x = mkName "x"@@ -259,7 +259,7 @@     mkClause conName types = do       body <- case concat vars of         [y] -> [e| $y |]-        _ -> [e| error "complex patterns are not supported" |]+        _   -> [e| error "complex patterns are not supported" |]       return [ Clause [ConP conName [] pats] (NormalB body) [] ]       where         x = mkName "x"
src/Control/Monad/Free/Foil/TH/PatternSynonyms.hs view
@@ -5,8 +5,7 @@ {-# LANGUAGE ViewPatterns    #-} module Control.Monad.Free.Foil.TH.PatternSynonyms where -import Control.Monad (forM_)-import qualified Control.Monad.Foil         as Foil+import           Control.Monad              (forM_) import           Control.Monad.Foil.TH.Util import           Control.Monad.Free.Foil import           Language.Haskell.TH@@ -61,7 +60,8 @@    where     n = mkName "n"-    termType = PeelConT ''AST [signatureType, VarT n]+    binderT = VarT (mkName "binder")+    termType = PeelConT ''AST [binderT, signatureType, VarT n]     toArg = \case       Left ((b, _), (x, _)) -> ConP 'ScopedAST [] [VarP b, VarP x]       Right (x, _) -> VarP x@@ -69,10 +69,10 @@     toPatternArgType i (_bang, VarT typeName)       | typeName == scope =           Left-            ( (mkName ("b" ++ show i), PeelConT ''Foil.NameBinder [VarT n, VarT l])-            , (mkName ("x" ++ show i), PeelConT ''AST [signatureType, VarT l]))+            ( (mkName ("b" ++ show i), foldl AppT binderT [VarT n, VarT l])+            , (mkName ("x" ++ show i), PeelConT ''AST [binderT, signatureType, VarT l]))       | typeName == term =-          Right (mkName ("x" ++ show i), PeelConT ''AST [signatureType, VarT n])+          Right (mkName ("x" ++ show i), PeelConT ''AST [binderT, signatureType, VarT n])       where         l = mkName ("l" ++ show i)     toPatternArgType i (_bang, type_)
src/Control/Monad/Free/Foil/TH/ZipMatch.hs view
@@ -1,7 +1,7 @@-{-# LANGUAGE LambdaCase      #-} {-# OPTIONS_GHC -fno-warn-type-defaults      #-}-{-# LANGUAGE ViewPatterns      #-}+{-# LANGUAGE LambdaCase      #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns    #-} module Control.Monad.Free.Foil.TH.ZipMatch where  import           Language.Haskell.TH