packages feed

blanks 0.4.2 → 0.5.0

raw patch · 25 files changed

+1183/−636 lines, 25 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Blanks.Interface: blankAbstract :: (Blank g, Eq a) => BlankInfo g -> Seq a -> g a -> BlankRight g (g a)
- Blanks.Interface: blankAbstract1 :: (Blank g, Eq a) => BlankInfo g -> a -> g a -> BlankRight g (g a)
- Blanks.Interface: blankApply :: Blank g => Seq (BlankRight g (g a)) -> g a -> Either SubError (g a)
- Blanks.Interface: blankApply1 :: Blank g => BlankRight g (g a) -> g a -> Either SubError (g a)
- Blanks.Interface: blankApply1Throw :: (Blank g, ThrowSub m, Applicative m) => BlankRight g (g a) -> g a -> m (g a)
- Blanks.Interface: blankApplyThrow :: (Blank g, ThrowSub m, Applicative m) => Seq (BlankRight g (g a)) -> g a -> m (g a)
- Blanks.Interface: blankBind :: Blank g => (a -> BlankRight g (g b)) -> g a -> g b
- Blanks.Interface: blankBindOpt :: Blank g => (a -> Maybe (BlankRight g (g a))) -> g a -> g a
- Blanks.Interface: blankEmbed :: Blank g => BlankFunctor g (g a) -> BlankRight g (g a)
- Blanks.Interface: blankFold :: Blank g => BlankFold g a r -> g a -> r
- Blanks.Interface: blankFree :: Blank g => a -> BlankRight g (g a)
- Blanks.Interface: blankHoistAnno :: BlankPair g h => (forall x. BlankLeft g x -> BlankLeft h x) -> g a -> h a
- Blanks.Interface: blankInstantiate :: Blank g => Seq (BlankRight g (g a)) -> g a -> g a
- Blanks.Interface: blankInstantiate1 :: Blank g => BlankRight g (g a) -> g a -> g a
- Blanks.Interface: blankLift :: (Blank g, Monad (BlankRight g), Traversable (BlankFunctor g)) => BlankFunctor g a -> BlankRight g (g a)
- Blanks.Interface: blankLiftAnno :: Blank g => BlankLeft g a -> g a
- Blanks.Interface: blankMapAnno :: Blank g => (BlankLeft g a -> BlankLeft g b) -> g a -> g b
- Blanks.Interface: blankRawFold :: Blank g => BlankRawFold g a r -> g a -> BlankLeft g r
- Blanks.Interface: blankUnAbstract :: Blank g => Seq a -> g a -> g a
- Blanks.Interface: blankUnAbstract1 :: Blank g => a -> g a -> g a
- Blanks.Interface: class (Adjunction (BlankLeft g) (BlankRight g), Applicative (BlankRight g), Functor (BlankFunctor g), NatNewtype (ScopeW (BlankLeft g) (BlankInfo g) (BlankFunctor g) g) g) => Blank (g :: Type -> Type)
- Blanks.Interface: type BlankFold (g :: Type -> Type) (a :: Type) (r :: Type) = BlankRawFold g a (BlankRight g r)
- Blanks.Interface: type BlankPair g h = (Blank g, Blank h, BlankInfo g ~ BlankInfo h, BlankFunctor g ~ BlankFunctor h)
- Blanks.Interface: type BlankRawFold (g :: Type -> Type) (a :: Type) (r :: Type) = UnderScopeFold (BlankInfo g) (BlankFunctor g) (g a) a r
- Blanks.Interface: type family BlankFunctor (g :: Type -> Type) :: Type -> Type
- Blanks.LocScope: instance GHC.Base.Functor f => Blanks.Interface.Blank (Blanks.LocScope.LocScope l n f)
- Blanks.LocScope: locScopeForget :: Functor f => LocScope l n f a -> Scope n f a
- Blanks.Located: [_locatedLoc] :: Located l a -> !l
- Blanks.Located: [_locatedVal] :: Located l a -> a
- Blanks.Name: [_nameKey] :: Name n a -> !n
- Blanks.Name: [_nameValue] :: Name n a -> !a
- Blanks.Scope: instance GHC.Base.Functor f => Blanks.Interface.Blank (Blanks.Scope.Scope n f)
- Blanks.ScopeW: instance Control.DeepSeq.NFData (t (Blanks.UnderScope.UnderScope n f (g a) a)) => Control.DeepSeq.NFData (Blanks.ScopeW.ScopeW t n f g a)
- Blanks.ScopeW: instance GHC.Classes.Eq (t (Blanks.UnderScope.UnderScope n f (g a) a)) => GHC.Classes.Eq (Blanks.ScopeW.ScopeW t n f g a)
- Blanks.ScopeW: instance GHC.Show.Show (t (Blanks.UnderScope.UnderScope n f (g a) a)) => GHC.Show.Show (Blanks.ScopeW.ScopeW t n f g a)
- Blanks.ScopeW: scopeWFold :: (NatNewtype (ScopeW t n f g) g, Adjunction t u) => ScopeWFold u n f g a r -> g a -> r
- Blanks.ScopeW: scopeWRawFold :: (NatNewtype (ScopeW t n f g) g, Functor t) => ScopeWRawFold n f g a r -> g a -> t r
- Blanks.ScopeW: type ScopeC t u n f g = (Adjunction t u, Applicative u, Functor f, NatNewtype (ScopeW t n f g) g)
- Blanks.ScopeW: type ScopeWFold u n f g a r = ScopeWRawFold n f g a (u r)
- Blanks.ScopeW: type ScopeWRawFold n f g a r = UnderScopeFold n f (g a) a r
- Blanks.UnderScope: BinderScope :: !Int -> !n -> e -> BinderScope n e
- Blanks.UnderScope: BoundScope :: Int -> BoundScope
- Blanks.UnderScope: EmbedScope :: f e -> EmbedScope f e
- Blanks.UnderScope: FreeScope :: a -> FreeScope a
- Blanks.UnderScope: UnderBinderScope :: !BinderScope n e -> UnderScope n f e a
- Blanks.UnderScope: UnderBoundScope :: !BoundScope -> UnderScope n f e a
- Blanks.UnderScope: UnderEmbedScope :: !EmbedScope f e -> UnderScope n f e a
- Blanks.UnderScope: UnderFreeScope :: !FreeScope a -> UnderScope n f e a
- Blanks.UnderScope: UnderScopeFold :: (BoundScope -> r) -> (FreeScope a -> r) -> (BinderScope n e -> r) -> (EmbedScope f e -> r) -> UnderScopeFold n f e a r
- Blanks.UnderScope: [binderScopeArity] :: BinderScope n e -> !Int
- Blanks.UnderScope: [binderScopeBody] :: BinderScope n e -> e
- Blanks.UnderScope: [binderScopeInfo] :: BinderScope n e -> !n
- Blanks.UnderScope: [unBoundScope] :: BoundScope -> Int
- Blanks.UnderScope: [unEmbedScope] :: EmbedScope f e -> f e
- Blanks.UnderScope: [unFreeScope] :: FreeScope a -> a
- Blanks.UnderScope: [usfBinder] :: UnderScopeFold n f e a r -> BinderScope n e -> r
- Blanks.UnderScope: [usfBound] :: UnderScopeFold n f e a r -> BoundScope -> r
- Blanks.UnderScope: [usfEmbed] :: UnderScopeFold n f e a r -> EmbedScope f e -> r
- Blanks.UnderScope: [usfFree] :: UnderScopeFold n f e a r -> FreeScope a -> r
- Blanks.UnderScope: data BinderScope n e
- Blanks.UnderScope: data UnderScope n f e a
- Blanks.UnderScope: data UnderScopeFold n f e a r
- Blanks.UnderScope: instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData n, Control.DeepSeq.NFData e, Control.DeepSeq.NFData (f e)) => Control.DeepSeq.NFData (Blanks.UnderScope.UnderScope n f e a)
- Blanks.UnderScope: instance (Control.DeepSeq.NFData n, Control.DeepSeq.NFData e) => Control.DeepSeq.NFData (Blanks.UnderScope.BinderScope n e)
- Blanks.UnderScope: instance (GHC.Classes.Eq a, GHC.Classes.Eq n, GHC.Classes.Eq e, GHC.Classes.Eq (f e)) => GHC.Classes.Eq (Blanks.UnderScope.UnderScope n f e a)
- Blanks.UnderScope: instance (GHC.Classes.Eq n, GHC.Classes.Eq e) => GHC.Classes.Eq (Blanks.UnderScope.BinderScope n e)
- Blanks.UnderScope: instance (GHC.Show.Show a, GHC.Show.Show n, GHC.Show.Show e, GHC.Show.Show (f e)) => GHC.Show.Show (Blanks.UnderScope.UnderScope n f e a)
- Blanks.UnderScope: instance (GHC.Show.Show n, GHC.Show.Show e) => GHC.Show.Show (Blanks.UnderScope.BinderScope n e)
- Blanks.UnderScope: instance Control.DeepSeq.NFData (f e) => Control.DeepSeq.NFData (Blanks.UnderScope.EmbedScope f e)
- Blanks.UnderScope: instance Control.DeepSeq.NFData Blanks.UnderScope.BoundScope
- Blanks.UnderScope: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Blanks.UnderScope.FreeScope a)
- Blanks.UnderScope: instance Data.Foldable.Foldable (Blanks.UnderScope.BinderScope n)
- Blanks.UnderScope: instance Data.Foldable.Foldable Blanks.UnderScope.FreeScope
- Blanks.UnderScope: instance Data.Foldable.Foldable f => Data.Bifoldable.Bifoldable (Blanks.UnderScope.UnderScope n f)
- Blanks.UnderScope: instance Data.Traversable.Traversable (Blanks.UnderScope.BinderScope n)
- Blanks.UnderScope: instance Data.Traversable.Traversable Blanks.UnderScope.FreeScope
- Blanks.UnderScope: instance Data.Traversable.Traversable f => Data.Bitraversable.Bitraversable (Blanks.UnderScope.UnderScope n f)
- Blanks.UnderScope: instance GHC.Base.Functor (Blanks.UnderScope.BinderScope n)
- Blanks.UnderScope: instance GHC.Base.Functor (Blanks.UnderScope.UnderScope n f e)
- Blanks.UnderScope: instance GHC.Base.Functor (Blanks.UnderScope.UnderScopeFold n f e a)
- Blanks.UnderScope: instance GHC.Base.Functor Blanks.UnderScope.FreeScope
- Blanks.UnderScope: instance GHC.Base.Functor f => Data.Bifunctor.Bifunctor (Blanks.UnderScope.UnderScope n f)
- Blanks.UnderScope: instance GHC.Base.Functor f => GHC.Base.Functor (Blanks.UnderScope.EmbedScope f)
- Blanks.UnderScope: instance GHC.Classes.Eq (f e) => GHC.Classes.Eq (Blanks.UnderScope.EmbedScope f e)
- Blanks.UnderScope: instance GHC.Classes.Eq Blanks.UnderScope.BoundScope
- Blanks.UnderScope: instance GHC.Classes.Eq a => GHC.Classes.Eq (Blanks.UnderScope.FreeScope a)
- Blanks.UnderScope: instance GHC.Generics.Generic (Blanks.UnderScope.BinderScope n e)
- Blanks.UnderScope: instance GHC.Generics.Generic (Blanks.UnderScope.UnderScope n f e a)
- Blanks.UnderScope: instance GHC.Show.Show (f e) => GHC.Show.Show (Blanks.UnderScope.EmbedScope f e)
- Blanks.UnderScope: instance GHC.Show.Show Blanks.UnderScope.BoundScope
- Blanks.UnderScope: instance GHC.Show.Show a => GHC.Show.Show (Blanks.UnderScope.FreeScope a)
- Blanks.UnderScope: newtype BoundScope
- Blanks.UnderScope: newtype EmbedScope f e
- Blanks.UnderScope: newtype FreeScope a
- Blanks.UnderScope: pattern UnderScopeBinder :: Int -> n -> e -> UnderScope n f e a
- Blanks.UnderScope: pattern UnderScopeBound :: Int -> UnderScope n f e a
- Blanks.UnderScope: pattern UnderScopeEmbed :: f e -> UnderScope n f e a
- Blanks.UnderScope: pattern UnderScopeFree :: a -> UnderScope n f e a
- Blanks.UnderScope: underScopeFold :: UnderScopeFold n f e a r -> UnderScope n f e a -> r
- Blanks.UnderScope: underScopeShift :: Functor f => (Int -> Int -> e -> e) -> Int -> Int -> UnderScope n f e a -> UnderScope n f e a
+ Blanks: BinderScope :: !Int -> !n -> e -> BinderScope n e
+ Blanks: [binderScopeArity] :: BinderScope n e -> !Int
+ Blanks: [binderScopeBody] :: BinderScope n e -> e
+ Blanks: [binderScopeInfo] :: BinderScope n e -> !n
+ Blanks: data BinderScope n e
+ Blanks.Conversion: locScopeForget :: Functor f => LocScope l n f a -> Scope n f a
+ Blanks.Conversion: scopeAnno :: Functor f => l -> Scope n f a -> LocScope l n f a
+ Blanks.Core: BinderScope :: !Int -> !n -> e -> BinderScope n e
+ Blanks.Core: BoundScope :: Int -> BoundScope
+ Blanks.Core: EmbedScope :: f e -> EmbedScope f e
+ Blanks.Core: FreeScope :: a -> FreeScope a
+ Blanks.Core: [binderScopeArity] :: BinderScope n e -> !Int
+ Blanks.Core: [binderScopeBody] :: BinderScope n e -> e
+ Blanks.Core: [binderScopeInfo] :: BinderScope n e -> !n
+ Blanks.Core: [unBoundScope] :: BoundScope -> Int
+ Blanks.Core: [unEmbedScope] :: EmbedScope f e -> f e
+ Blanks.Core: [unFreeScope] :: FreeScope a -> a
+ Blanks.Core: data BinderScope n e
+ Blanks.Core: instance (Control.DeepSeq.NFData n, Control.DeepSeq.NFData e) => Control.DeepSeq.NFData (Blanks.Core.BinderScope n e)
+ Blanks.Core: instance (GHC.Classes.Eq n, GHC.Classes.Eq e) => GHC.Classes.Eq (Blanks.Core.BinderScope n e)
+ Blanks.Core: instance (GHC.Show.Show n, GHC.Show.Show e) => GHC.Show.Show (Blanks.Core.BinderScope n e)
+ Blanks.Core: instance Control.DeepSeq.NFData (f e) => Control.DeepSeq.NFData (Blanks.Core.EmbedScope f e)
+ Blanks.Core: instance Control.DeepSeq.NFData Blanks.Core.BoundScope
+ Blanks.Core: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Blanks.Core.FreeScope a)
+ Blanks.Core: instance Data.Foldable.Foldable (Blanks.Core.BinderScope n)
+ Blanks.Core: instance Data.Foldable.Foldable Blanks.Core.FreeScope
+ Blanks.Core: instance Data.Traversable.Traversable (Blanks.Core.BinderScope n)
+ Blanks.Core: instance Data.Traversable.Traversable Blanks.Core.FreeScope
+ Blanks.Core: instance GHC.Base.Functor (Blanks.Core.BinderScope n)
+ Blanks.Core: instance GHC.Base.Functor Blanks.Core.FreeScope
+ Blanks.Core: instance GHC.Base.Functor f => GHC.Base.Functor (Blanks.Core.EmbedScope f)
+ Blanks.Core: instance GHC.Classes.Eq (f e) => GHC.Classes.Eq (Blanks.Core.EmbedScope f e)
+ Blanks.Core: instance GHC.Classes.Eq Blanks.Core.BoundScope
+ Blanks.Core: instance GHC.Classes.Eq a => GHC.Classes.Eq (Blanks.Core.FreeScope a)
+ Blanks.Core: instance GHC.Generics.Generic (Blanks.Core.BinderScope n e)
+ Blanks.Core: instance GHC.Show.Show (f e) => GHC.Show.Show (Blanks.Core.EmbedScope f e)
+ Blanks.Core: instance GHC.Show.Show Blanks.Core.BoundScope
+ Blanks.Core: instance GHC.Show.Show a => GHC.Show.Show (Blanks.Core.FreeScope a)
+ Blanks.Core: newtype BoundScope
+ Blanks.Core: newtype EmbedScope f e
+ Blanks.Core: newtype FreeScope a
+ Blanks.LocScope: locScopeAbstract :: (Functor f, Eq a) => n -> Seq a -> LocScope l n f a -> Colocated l (LocScope l n f a)
+ Blanks.LocScope: locScopeAbstract1 :: (Functor f, Eq a) => n -> a -> LocScope l n f a -> Colocated l (LocScope l n f a)
+ Blanks.LocScope: locScopeApply :: Functor f => Seq (Colocated l (LocScope l n f a)) -> LocScope l n f a -> Either SubError (LocScope l n f a)
+ Blanks.LocScope: locScopeApply1 :: Functor f => Colocated l (LocScope l n f a) -> LocScope l n f a -> Either SubError (LocScope l n f a)
+ Blanks.LocScope: locScopeBind :: Functor f => (a -> Colocated l (LocScope l n f b)) -> LocScope l n f a -> LocScope l n f b
+ Blanks.LocScope: locScopeBindOpt :: Functor f => (a -> Maybe (Colocated l (LocScope l n f a))) -> LocScope l n f a -> LocScope l n f a
+ Blanks.LocScope: locScopeEmbed :: Functor f => f (LocScope l n f a) -> Colocated l (LocScope l n f a)
+ Blanks.LocScope: locScopeFree :: Functor f => a -> Colocated l (LocScope l n f a)
+ Blanks.LocScope: locScopeFromInnerBinder :: Functor f => BinderScope n (LocScope l n f a) -> Colocated l (LocScope l n f a)
+ Blanks.LocScope: locScopeHoistAnno :: Functor f => (l -> x) -> LocScope l n f a -> LocScope x n f a
+ Blanks.LocScope: locScopeInnerBinder :: (Functor f, Eq a) => n -> Seq a -> LocScope l n f a -> BinderScope n (LocScope l n f a)
+ Blanks.LocScope: locScopeInnerBinder1 :: (Functor f, Eq a) => n -> a -> LocScope l n f a -> BinderScope n (LocScope l n f a)
+ Blanks.LocScope: locScopeInstantiate :: Functor f => Seq (Colocated l (LocScope l n f a)) -> LocScope l n f a -> LocScope l n f a
+ Blanks.LocScope: locScopeInstantiate1 :: Functor f => Colocated l (LocScope l n f a) -> LocScope l n f a -> LocScope l n f a
+ Blanks.LocScope: locScopeLift :: Traversable f => f a -> Colocated l (LocScope l n f a)
+ Blanks.LocScope: locScopeLiftAnno :: Located l a -> LocScope l n f a
+ Blanks.LocScope: locScopeMapAnno :: Functor f => (Located l a -> Located l b) -> LocScope l n f a -> LocScope l n f b
+ Blanks.LocScope: locScopeUnAbstract :: Functor f => Seq a -> LocScope l n f a -> LocScope l n f a
+ Blanks.LocScope: locScopeUnAbstract1 :: Functor f => a -> LocScope l n f a -> LocScope l n f a
+ Blanks.Located: [locatedLoc] :: Located l a -> !l
+ Blanks.Located: [locatedVal] :: Located l a -> a
+ Blanks.Name: [nameKey] :: Name n a -> !n
+ Blanks.Name: [nameValue] :: Name n a -> !a
+ Blanks.Scope: scopeAbstract :: (Functor f, Eq a) => n -> Seq a -> Scope n f a -> Scope n f a
+ Blanks.Scope: scopeAbstract1 :: (Functor f, Eq a) => n -> a -> Scope n f a -> Scope n f a
+ Blanks.Scope: scopeApply :: Functor f => Seq (Scope n f a) -> Scope n f a -> Either SubError (Scope n f a)
+ Blanks.Scope: scopeApply1 :: Functor f => Scope n f a -> Scope n f a -> Either SubError (Scope n f a)
+ Blanks.Scope: scopeBind :: Functor f => (a -> Scope n f b) -> Scope n f a -> Scope n f b
+ Blanks.Scope: scopeBindOpt :: Functor f => (a -> Maybe (Scope n f a)) -> Scope n f a -> Scope n f a
+ Blanks.Scope: scopeInnerBinder :: (Functor f, Eq a) => n -> Seq a -> Scope n f a -> BinderScope n (Scope n f a)
+ Blanks.Scope: scopeInnerBinder1 :: (Functor f, Eq a) => n -> a -> Scope n f a -> BinderScope n (Scope n f a)
+ Blanks.Scope: scopeInstantiate :: Functor f => Seq (Scope n f a) -> Scope n f a -> Scope n f a
+ Blanks.Scope: scopeInstantiate1 :: Functor f => Scope n f a -> Scope n f a -> Scope n f a
+ Blanks.Scope: scopeLift :: Traversable f => f a -> Scope n f a
+ Blanks.Scope: scopeUnAbstract :: Functor f => Seq a -> Scope n f a -> Scope n f a
+ Blanks.Scope: scopeUnAbstract1 :: Functor f => a -> Scope n f a -> Scope n f a
+ Blanks.Scope: scopeWFromInnerBinder :: ScopeWC t u n f g => BinderScope n (g a) -> u (g a)
+ Blanks.ScopeW: instance Control.DeepSeq.NFData (t (Blanks.Under.UnderScope n f (g a) a)) => Control.DeepSeq.NFData (Blanks.ScopeW.ScopeW t n f g a)
+ Blanks.ScopeW: instance GHC.Classes.Eq (t (Blanks.Under.UnderScope n f (g a) a)) => GHC.Classes.Eq (Blanks.ScopeW.ScopeW t n f g a)
+ Blanks.ScopeW: instance GHC.Show.Show (t (Blanks.Under.UnderScope n f (g a) a)) => GHC.Show.Show (Blanks.ScopeW.ScopeW t n f g a)
+ Blanks.ScopeW: scopeWAbstract1 :: (ScopeWC t u n f g, Eq a) => n -> a -> g a -> u (g a)
+ Blanks.ScopeW: scopeWApply1 :: ScopeWC t u n f g => u (g a) -> g a -> Either SubError (g a)
+ Blanks.ScopeW: scopeWFromInnerBinder :: ScopeWC t u n f g => BinderScope n (g a) -> u (g a)
+ Blanks.ScopeW: scopeWInnerBinder :: (ScopeWC t u n f g, Eq a) => n -> Seq a -> g a -> BinderScope n (g a)
+ Blanks.ScopeW: scopeWInnerBinder1 :: (ScopeWC t u n f g, Eq a) => n -> a -> g a -> BinderScope n (g a)
+ Blanks.ScopeW: scopeWInstantiate1 :: ScopeWC t u n f g => u (g a) -> g a -> g a
+ Blanks.ScopeW: scopeWUnAbstract1 :: ScopeWC t u n f g => a -> g a -> g a
+ Blanks.ScopeW: type ScopeWC t u n f g = (Adjunction t u, Applicative u, Functor f, NatNewtype (ScopeW t n f g) g)
+ Blanks.Split: BinderId :: Int -> BinderId
+ Blanks.Split: SplitBinder :: !Int -> !Set a -> !BinderScope n (LocScope l n (SplitFunctor f) a) -> SplitBinder l n f a
+ Blanks.Split: SplitFunctorBase :: !f a -> SplitFunctor f a
+ Blanks.Split: SplitFunctorClosure :: !BinderId -> !Seq Int -> SplitFunctor f a
+ Blanks.Split: SplitResult :: !Tracked a -> !LocScope l n (SplitFunctor f) a -> !Map BinderId (SplitBinder l n f a) -> SplitResult l n f a
+ Blanks.Split: [splitBinderClosureArity] :: SplitBinder l n f a -> !Int
+ Blanks.Split: [splitBinderFree] :: SplitBinder l n f a -> !Set a
+ Blanks.Split: [splitBinderScope] :: SplitBinder l n f a -> !BinderScope n (LocScope l n (SplitFunctor f) a)
+ Blanks.Split: [splitResultBinders] :: SplitResult l n f a -> !Map BinderId (SplitBinder l n f a)
+ Blanks.Split: [splitResultScope] :: SplitResult l n f a -> !LocScope l n (SplitFunctor f) a
+ Blanks.Split: [splitResultTracked] :: SplitResult l n f a -> !Tracked a
+ Blanks.Split: [unBinderId] :: BinderId -> Int
+ Blanks.Split: data SplitBinder l n f a
+ Blanks.Split: data SplitFunctor f a
+ Blanks.Split: data SplitResult l n f a
+ Blanks.Split: instance (Control.DeepSeq.NFData l, Control.DeepSeq.NFData n, Control.DeepSeq.NFData a, Control.DeepSeq.NFData (f (Blanks.LocScope.LocScope l n (Blanks.Split.SplitFunctor f) a))) => Control.DeepSeq.NFData (Blanks.Split.SplitBinder l n f a)
+ Blanks.Split: instance (GHC.Classes.Eq l, GHC.Classes.Eq n, GHC.Classes.Eq a, GHC.Classes.Eq (f (Blanks.LocScope.LocScope l n (Blanks.Split.SplitFunctor f) a))) => GHC.Classes.Eq (Blanks.Split.SplitBinder l n f a)
+ Blanks.Split: instance (GHC.Show.Show l, GHC.Show.Show n, GHC.Show.Show a, GHC.Show.Show (f (Blanks.LocScope.LocScope l n (Blanks.Split.SplitFunctor f) a))) => GHC.Show.Show (Blanks.Split.SplitBinder l n f a)
+ Blanks.Split: instance Control.DeepSeq.NFData (f a) => Control.DeepSeq.NFData (Blanks.Split.SplitFunctor f a)
+ Blanks.Split: instance Control.DeepSeq.NFData Blanks.Split.BinderId
+ Blanks.Split: instance Data.Foldable.Foldable f => Data.Foldable.Foldable (Blanks.Split.SplitFunctor f)
+ Blanks.Split: instance Data.Traversable.Traversable f => Data.Traversable.Traversable (Blanks.Split.SplitFunctor f)
+ Blanks.Split: instance GHC.Base.Functor f => GHC.Base.Functor (Blanks.Split.SplitFunctor f)
+ Blanks.Split: instance GHC.Classes.Eq (f a) => GHC.Classes.Eq (Blanks.Split.SplitFunctor f a)
+ Blanks.Split: instance GHC.Classes.Eq Blanks.Split.BinderId
+ Blanks.Split: instance GHC.Classes.Ord Blanks.Split.BinderId
+ Blanks.Split: instance GHC.Enum.Enum Blanks.Split.BinderId
+ Blanks.Split: instance GHC.Generics.Generic (Blanks.Split.SplitBinder l n f a)
+ Blanks.Split: instance GHC.Generics.Generic (Blanks.Split.SplitFunctor f a)
+ Blanks.Split: instance GHC.Num.Num Blanks.Split.BinderId
+ Blanks.Split: instance GHC.Show.Show (f a) => GHC.Show.Show (Blanks.Split.SplitFunctor f a)
+ Blanks.Split: instance GHC.Show.Show Blanks.Split.BinderId
+ Blanks.Split: newtype BinderId
+ Blanks.Split: splitLocScope :: (Traversable f, Ord a) => LocScope (WithTracked a l) n f a -> SplitResult l n f a
+ Blanks.Tracked: Tracked :: !Set a -> !Set Int -> Tracked a
+ Blanks.Tracked: WithTracked :: !Tracked a -> !l -> WithTracked a l
+ Blanks.Tracked: [trackedBound] :: Tracked a -> !Set Int
+ Blanks.Tracked: [trackedFree] :: Tracked a -> !Set a
+ Blanks.Tracked: [withTrackedEnv] :: WithTracked a l -> !l
+ Blanks.Tracked: [withTrackedState] :: WithTracked a l -> !Tracked a
+ Blanks.Tracked: data Tracked a
+ Blanks.Tracked: data WithTracked a l
+ Blanks.Tracked: forgetTrackedScope :: Functor f => LocScope (WithTracked a l) n f z -> LocScope l n f z
+ Blanks.Tracked: instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData l) => Control.DeepSeq.NFData (Blanks.Tracked.WithTracked a l)
+ Blanks.Tracked: instance (GHC.Classes.Eq a, GHC.Classes.Eq l) => GHC.Classes.Eq (Blanks.Tracked.WithTracked a l)
+ Blanks.Tracked: instance (GHC.Show.Show a, GHC.Show.Show l) => GHC.Show.Show (Blanks.Tracked.WithTracked a l)
+ Blanks.Tracked: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Blanks.Tracked.Tracked a)
+ Blanks.Tracked: instance Data.Foldable.Foldable (Blanks.Tracked.WithTracked a)
+ Blanks.Tracked: instance Data.Traversable.Traversable (Blanks.Tracked.WithTracked a)
+ Blanks.Tracked: instance GHC.Base.Functor (Blanks.Tracked.WithTracked a)
+ Blanks.Tracked: instance GHC.Classes.Eq a => GHC.Classes.Eq (Blanks.Tracked.Tracked a)
+ Blanks.Tracked: instance GHC.Classes.Ord a => GHC.Base.Monoid (Blanks.Tracked.Tracked a)
+ Blanks.Tracked: instance GHC.Classes.Ord a => GHC.Base.Semigroup (Blanks.Tracked.Tracked a)
+ Blanks.Tracked: instance GHC.Generics.Generic (Blanks.Tracked.Tracked a)
+ Blanks.Tracked: instance GHC.Generics.Generic (Blanks.Tracked.WithTracked a l)
+ Blanks.Tracked: instance GHC.Show.Show a => GHC.Show.Show (Blanks.Tracked.Tracked a)
+ Blanks.Tracked: mkTrackedBound :: Int -> Tracked a
+ Blanks.Tracked: mkTrackedFree :: a -> Tracked a
+ Blanks.Tracked: shiftTracked :: Int -> Tracked a -> Tracked a
+ Blanks.Tracked: trackScope :: (Traversable f, Ord a) => LocScope l n f a -> LocScope (WithTracked a l) n f a
+ Blanks.Tracked: trackScopeSimple :: (Traversable f, Ord a) => Scope n f a -> LocScope (Tracked a) n f a
+ Blanks.Under: UnderBinderScope :: !BinderScope n e -> UnderScope n f e a
+ Blanks.Under: UnderBoundScope :: !BoundScope -> UnderScope n f e a
+ Blanks.Under: UnderEmbedScope :: !EmbedScope f e -> UnderScope n f e a
+ Blanks.Under: UnderFreeScope :: !FreeScope a -> UnderScope n f e a
+ Blanks.Under: data UnderScope n f e a
+ Blanks.Under: instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData n, Control.DeepSeq.NFData e, Control.DeepSeq.NFData (f e)) => Control.DeepSeq.NFData (Blanks.Under.UnderScope n f e a)
+ Blanks.Under: instance (GHC.Classes.Eq a, GHC.Classes.Eq n, GHC.Classes.Eq e, GHC.Classes.Eq (f e)) => GHC.Classes.Eq (Blanks.Under.UnderScope n f e a)
+ Blanks.Under: instance (GHC.Show.Show a, GHC.Show.Show n, GHC.Show.Show e, GHC.Show.Show (f e)) => GHC.Show.Show (Blanks.Under.UnderScope n f e a)
+ Blanks.Under: instance Data.Foldable.Foldable f => Data.Bifoldable.Bifoldable (Blanks.Under.UnderScope n f)
+ Blanks.Under: instance Data.Traversable.Traversable f => Data.Bitraversable.Bitraversable (Blanks.Under.UnderScope n f)
+ Blanks.Under: instance GHC.Base.Functor (Blanks.Under.UnderScope n f e)
+ Blanks.Under: instance GHC.Base.Functor f => Data.Bifunctor.Bifunctor (Blanks.Under.UnderScope n f)
+ Blanks.Under: instance GHC.Generics.Generic (Blanks.Under.UnderScope n f e a)
+ Blanks.Under: pattern UnderScopeBinder :: Int -> n -> e -> UnderScope n f e a
+ Blanks.Under: pattern UnderScopeBound :: Int -> UnderScope n f e a
+ Blanks.Under: pattern UnderScopeEmbed :: f e -> UnderScope n f e a
+ Blanks.Under: pattern UnderScopeFree :: a -> UnderScope n f e a
+ Blanks.Under: underScopeShift :: Functor f => (Int -> Int -> e -> e) -> Int -> Int -> UnderScope n f e a -> UnderScope n f e a
- Blanks.ScopeW: scopeWAbstract :: (ScopeC t u n f g, Eq a) => n -> Seq a -> g a -> u (g a)
+ Blanks.ScopeW: scopeWAbstract :: (ScopeWC t u n f g, Eq a) => n -> Seq a -> g a -> u (g a)
- Blanks.ScopeW: scopeWApply :: ScopeC t u n f g => Seq (u (g a)) -> g a -> Either SubError (g a)
+ Blanks.ScopeW: scopeWApply :: ScopeWC t u n f g => Seq (u (g a)) -> g a -> Either SubError (g a)
- Blanks.ScopeW: scopeWBind :: ScopeC t u n f g => (a -> u (g b)) -> g a -> g b
+ Blanks.ScopeW: scopeWBind :: ScopeWC t u n f g => (a -> u (g b)) -> g a -> g b
- Blanks.ScopeW: scopeWBindOpt :: ScopeC t u n f g => (a -> Maybe (u (g a))) -> g a -> g a
+ Blanks.ScopeW: scopeWBindOpt :: ScopeWC t u n f g => (a -> Maybe (u (g a))) -> g a -> g a
- Blanks.ScopeW: scopeWEmbed :: ScopeC t u n f g => f (g a) -> u (g a)
+ Blanks.ScopeW: scopeWEmbed :: ScopeWC t u n f g => f (g a) -> u (g a)
- Blanks.ScopeW: scopeWFree :: ScopeC t u n f g => a -> u (g a)
+ Blanks.ScopeW: scopeWFree :: ScopeWC t u n f g => a -> u (g a)
- Blanks.ScopeW: scopeWInstantiate :: ScopeC t u n f g => Seq (u (g a)) -> g a -> g a
+ Blanks.ScopeW: scopeWInstantiate :: ScopeWC t u n f g => Seq (u (g a)) -> g a -> g a
- Blanks.ScopeW: scopeWLift :: (ScopeC t u n f g, Monad u, Traversable f) => f a -> u (g a)
+ Blanks.ScopeW: scopeWLift :: (ScopeWC t u n f g, Monad u, Traversable f) => f a -> u (g a)
- Blanks.ScopeW: scopeWMapAnno :: ScopeC t u n f g => (t a -> t b) -> g a -> g b
+ Blanks.ScopeW: scopeWMapAnno :: ScopeWC t u n f g => (t a -> t b) -> g a -> g b
- Blanks.ScopeW: scopeWUnAbstract :: ScopeC t u n f g => Seq a -> g a -> g a
+ Blanks.ScopeW: scopeWUnAbstract :: ScopeWC t u n f g => Seq a -> g a -> g a

Files

README.md view
@@ -19,6 +19,5 @@ bound variables), but if you stick to the provided combinators, things will work out fine.  You'll get most of what you want by just importing this module unqualified.-See the `Blanks` class definition and related methods to manipulate variables and abstractions. See `Scope` for the basic wrapper and `LocScope` for a wrapper with annotations you can use for source locations and the like. See the test suite for examples.
blanks.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: bce7c1157ad17dfb08bdd82fd1d9cef7f5aead112c1349019b6dbfed38de7959+-- hash: 3e66404b6e808993a99490ba1327e8e872e5dee4cfb34980b7cd5f84ce47aba6  name:           blanks-version:        0.4.2+version:        0.5.0 synopsis:       Fill-in-the-blanks - A library factoring out substitution from ASTs description:    Please see the README on GitHub at <https://github.com/ejconlon/blanks#readme> category:       Language@@ -29,20 +29,23 @@ library   exposed-modules:       Blanks-      Blanks.Interface+      Blanks.Conversion+      Blanks.Core       Blanks.Located       Blanks.LocScope       Blanks.Name       Blanks.NatNewtype       Blanks.Scope       Blanks.ScopeW+      Blanks.Split       Blanks.Sub-      Blanks.UnderScope+      Blanks.Tracked+      Blanks.Under   other-modules:       Paths_blanks   hs-source-dirs:       src-  default-extensions: BangPatterns ConstraintKinds DeriveFunctor DeriveFoldable DeriveGeneric DeriveTraversable DerivingStrategies FlexibleContexts FlexibleInstances FunctionalDependencies GeneralizedNewtypeDeriving KindSignatures MultiParamTypeClasses PatternSynonyms Rank2Types TypeFamilies+  default-extensions: BangPatterns ConstraintKinds DeriveFunctor DeriveFoldable DeriveGeneric DeriveTraversable DerivingStrategies DerivingVia FlexibleContexts FlexibleInstances FunctionalDependencies GeneralizedNewtypeDeriving KindSignatures MultiParamTypeClasses PatternSynonyms Rank2Types TypeFamilies   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints -fno-warn-unused-top-binds   build-depends:       adjunctions >=4.4 && <5@@ -58,13 +61,18 @@   main-is: Main.hs   other-modules:       Test.Blanks.Assertions-      Test.Blanks.LocScopeTest+      Test.Blanks.Exp+      Test.Blanks.ExpTest       Test.Blanks.Parsing       Test.Blanks.ScopeTest+      Test.Blanks.SimpleScope+      Test.Blanks.SplitScope+      Test.Blanks.SplitTest+      Test.Blanks.TrackedTest       Paths_blanks   hs-source-dirs:       test-  default-extensions: BangPatterns ConstraintKinds DeriveFunctor DeriveFoldable DeriveGeneric DeriveTraversable DerivingStrategies FlexibleContexts FlexibleInstances FunctionalDependencies GeneralizedNewtypeDeriving KindSignatures MultiParamTypeClasses PatternSynonyms Rank2Types TypeFamilies+  default-extensions: BangPatterns ConstraintKinds DeriveFunctor DeriveFoldable DeriveGeneric DeriveTraversable DerivingStrategies DerivingVia FlexibleContexts FlexibleInstances FunctionalDependencies GeneralizedNewtypeDeriving KindSignatures MultiParamTypeClasses PatternSynonyms Rank2Types TypeFamilies   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints -fno-warn-unused-top-binds -threaded -rtsopts -with-rtsopts=-N   build-depends:       adjunctions >=4.4 && <5
src/Blanks.hs view
@@ -1,14 +1,17 @@ -- | You'll get most of what you want by just importing this module unqualified.--- See the 'Blanks' class definition and related methods to manipulate variables and abstractions. -- See 'Scope' for the basic wrapper and 'LocScope' for a wrapper with annotations you can use -- for source locations and the like. See the test suite for examples. module Blanks   ( module Blanks+  , BinderScope (..)   ) where -import Blanks.Interface as Blanks+import Blanks.Conversion as Blanks+import Blanks.Core (BinderScope (..)) import Blanks.Located as Blanks import Blanks.LocScope as Blanks import Blanks.Name as Blanks import Blanks.Scope as Blanks+import Blanks.Split as Blanks import Blanks.Sub as Blanks+import Blanks.Tracked as Blanks
+ src/Blanks/Conversion.hs view
@@ -0,0 +1,27 @@+module Blanks.Conversion+  ( locScopeForget+  , scopeAnno+  ) where++import Blanks.LocScope (LocScope, pattern LocScopeBinder, pattern LocScopeBound, pattern LocScopeEmbed,+                        pattern LocScopeFree)+import Blanks.Scope (Scope, pattern ScopeBinder, pattern ScopeBound, pattern ScopeEmbed, pattern ScopeFree)++-- | Forget all the annotations and yield a plain 'Scope'.+locScopeForget :: Functor f => LocScope l n f a -> Scope n f a+locScopeForget ls =+  case ls of+    LocScopeBound _ b -> ScopeBound b+    LocScopeFree _ a -> ScopeFree a+    LocScopeBinder _ r x e -> ScopeBinder r x (locScopeForget e)+    LocScopeEmbed _ fe -> ScopeEmbed (fmap locScopeForget fe)++-- | Annotate every location in the 'Scope' with a given value as a 'LocScope'.+scopeAnno :: Functor f => l -> Scope n f a -> LocScope l n f a+scopeAnno l = go where+  go s =+    case s of+      ScopeBound b -> LocScopeBound l b+      ScopeFree a -> LocScopeFree l a+      ScopeBinder r x e -> LocScopeBinder l r x (go e)+      ScopeEmbed fe -> LocScopeEmbed l (fmap go fe)
+ src/Blanks/Core.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE DeriveAnyClass #-}++-- | Internals.+module Blanks.Core+  ( BoundScope (..)+  , FreeScope (..)+  , BinderScope (..)+  , EmbedScope (..)+  ) where++import Control.DeepSeq (NFData)+import GHC.Generics (Generic)++newtype BoundScope =+  BoundScope+    { unBoundScope :: Int+    }+  deriving newtype (Eq, Show, NFData)++newtype FreeScope a =+  FreeScope+    { unFreeScope :: a+    }+  deriving stock (Eq, Show, Functor, Foldable, Traversable)+  deriving newtype (NFData)++data BinderScope n e =+  BinderScope+    { binderScopeArity :: !Int+    , binderScopeInfo :: !n+    , binderScopeBody :: e+    }+  deriving stock (Eq, Show, Functor, Foldable, Traversable, Generic)+  deriving anyclass (NFData)++newtype EmbedScope f e =+  EmbedScope+    { unEmbedScope :: f e+    }+  deriving newtype (Eq, Show, Functor, NFData)
− src/Blanks/Interface.hs
@@ -1,209 +0,0 @@-module Blanks.Interface-  ( Blank-  , BlankLeft-  , BlankRight-  , BlankInfo-  , BlankFunctor-  , BlankRawFold-  , BlankFold-  , BlankPair-  , blankFree-  , blankEmbed-  , blankAbstract-  , blankAbstract1-  , blankUnAbstract-  , blankUnAbstract1-  , blankInstantiate-  , blankInstantiate1-  , blankApply-  , blankApply1-  , blankApplyThrow-  , blankApply1Throw-  , blankBind-  , blankBindOpt-  , blankLift-  , blankRawFold-  , blankFold-  , blankLiftAnno-  , blankHoistAnno-  , blankMapAnno-  ) where--import Blanks.NatNewtype (NatNewtype)-import Blanks.ScopeW-import Blanks.Sub (SubError, ThrowSub, rethrowSub)-import Blanks.UnderScope (UnderScopeFold)-import Data.Functor.Adjunction (Adjunction)-import Data.Kind (Type)-import Data.Sequence (Seq)-import qualified Data.Sequence as Seq---- | The left adjoint functor used by 'g'.-type family BlankLeft (g :: Type -> Type) :: Type -> Type---- | The right adjoint functor used by 'g'-type family BlankRight (g :: Type -> Type) :: Type -> Type---- | The binder info used by 'g'.-type family BlankInfo (g :: Type -> Type) :: Type---- | The expression functor used by 'g'.-type family BlankFunctor (g :: Type -> Type) :: Type -> Type--type BlankRawFold (g :: Type -> Type) (a :: Type) (r :: Type) = UnderScopeFold (BlankInfo g) (BlankFunctor g) (g a) a r-type BlankFold (g :: Type -> Type) (a :: Type) (r :: Type) = BlankRawFold g a (BlankRight g r)---- | Indicates that 'g' is a "scope" functor we can use for name-binding. (Behind-the-scenes, 'g' must--- be a newtype wrapper over the 'ScopeW' datatype.) Most of the time you will use 'Scope' or 'LocScope'--- directly, which are instances of this class.------ We use the pair of adjoint functors indexed by 'g' to shift the burden of operating in context--- where it is more convenient. For example, 'LocScope' uses a pair of functors that are--- essentially 'Env' and 'Reader'. The left adjoint 'Env' lets us annotate every level of our--- expression tree with a location, and the right adjoint 'Reader' informs us of that location--- so we don't have to make one up out of thin air!------ 'Scope' uses the pair of functors 'Identity' and 'Identity', which means there is--- no ability to store any additional information in the tree, but there's also no additional--- burden to provide that information.-class-  ( Adjunction (BlankLeft g) (BlankRight g)-  , Applicative (BlankRight g)-  , Functor (BlankFunctor g)-  , NatNewtype (ScopeW (BlankLeft g) (BlankInfo g) (BlankFunctor g) g) g-  ) => Blank (g :: Type -> Type)---- | A pair of 'Blank' functors that index the same info and embedded functors. Used to change adjoint functors.-type BlankPair g h = (Blank g, Blank h, BlankInfo g ~ BlankInfo h, BlankFunctor g ~ BlankFunctor h)---- | Creates a free variable in context.-blankFree ::-  Blank g-  => a -- ^ The name of the free variable-  -> BlankRight g (g a)-blankFree = scopeWFree-{-# INLINE blankFree #-}---- | Embeds an expression functor in context.-blankEmbed ::-  Blank g-  => BlankFunctor g (g a) -- ^ An expression-  -> BlankRight g (g a)-blankEmbed = scopeWEmbed-{-# INLINE blankEmbed #-}---- | Binds free variables in an expression and returns a binder.-blankAbstract ::-  (Blank g, Eq a)-  => BlankInfo g -- ^ Annotation specific to your expression functor.-                 -- Might contain original variable names and types, or might-                 -- mark this as a "let" vs a "lambda".-  -> Seq a -- ^ Free variables to bind, like the names of function parameters-  -> g a -- ^ The expression to bind in, like the body of a function-  -> BlankRight g (g a)-blankAbstract = scopeWAbstract-{-# INLINE blankAbstract #-}---- | 'blankAbstract' for a single argument.-blankAbstract1 :: (Blank g, Eq a) => BlankInfo g -> a -> g a -> BlankRight g (g a)-blankAbstract1 n k = scopeWAbstract n (Seq.singleton k)-{-# INLINE blankAbstract1 #-}---- | Un-bind free variables in an expression. Basically the inverse of--- 'blankAbstract'. Take care to match the arity of the binder! ('blankApply' is safer.)-blankUnAbstract ::-  Blank g-  => Seq a -- ^ The names of the variables you're freeing-  -> g a -- ^ The expression to substitutue in (typically a binder)-  -> g a-blankUnAbstract = scopeWUnAbstract-{-# INLINE blankUnAbstract #-}---- 'blankUnAbstract' for a single argument.-blankUnAbstract1 :: Blank g => a -> g a -> g a-blankUnAbstract1 = scopeWUnAbstract . Seq.singleton-{-# INLINE blankUnAbstract1 #-}---- | Instantiate the bound variables in an expression with other expressions.--- Take care to match the arity of the binder! ('blankApply' is safer.)-blankInstantiate ::-  Blank g-  => Seq (BlankRight g (g a)) -- ^ Expressions to substitute in place of bound vars-  -> g a -- ^ The expression to substitute in (typically a binder)-  -> g a-blankInstantiate = scopeWInstantiate-{-# INLINE blankInstantiate #-}---- | 'blankInstantiate' for a single argument.-blankInstantiate1 :: Blank g => BlankRight g (g a) -> g a -> g a-blankInstantiate1 = scopeWInstantiate . Seq.singleton-{-# INLINE blankInstantiate1 #-}---- | Instantiates the bound variables in an expression with other expressions.--- Throws errors on mismatched arity, non binder expression, unbound vars, etc.--- A version of 'blankInstantiate' that fails loudly instead of silently!-blankApply ::-  Blank g-  => Seq (BlankRight g (g a)) -- ^ Expressions to substitute in place of bound vars-  -> g a -- ^ The binder expression to substitute in-  -> Either SubError (g a)-blankApply = scopeWApply-{-# INLINE blankApply #-}---- | 'blankApply' for a single argument.-blankApply1 :: Blank g => BlankRight g (g a) -> g a -> Either SubError (g a)-blankApply1 = scopeWApply . Seq.singleton-{-# INLINE blankApply1 #-}---- | A 'ThrowSub' version of 'blankApply'.-blankApplyThrow :: (Blank g, ThrowSub m, Applicative m) => Seq (BlankRight g (g a)) -> g a -> m (g a)-blankApplyThrow ks = rethrowSub . scopeWApply ks-{-# INLINE blankApplyThrow #-}---- | A 'ThrowSub' version of 'blankApply1'.-blankApply1Throw :: (Blank g, ThrowSub m, Applicative m) => BlankRight g (g a) -> g a -> m (g a)-blankApply1Throw k = rethrowSub . scopeWApply (Seq.singleton k)-{-# INLINE blankApply1Throw #-}---- | Substitution as a kind of monadic bind.-blankBind :: Blank g => (a -> BlankRight g (g b)) -> g a -> g b-blankBind = scopeWBind-{-# INLINE blankBind #-}---- | Optional substitution as another kind of monadic bind.-blankBindOpt :: Blank g => (a -> Maybe (BlankRight g (g a))) -> g a -> g a-blankBindOpt = scopeWBindOpt-{-# INLINE blankBindOpt #-}---- | Lift an expression functor into the scope functor.-blankLift :: (Blank g, Monad (BlankRight g), Traversable (BlankFunctor g)) => BlankFunctor g a -> BlankRight g (g a)-blankLift = scopeWLift-{-# INLINE blankLift #-}---- | Pattern match all cases of the scope functor.-blankRawFold :: Blank g => BlankRawFold g a r -> g a -> BlankLeft g r-blankRawFold = scopeWRawFold-{-# INLINE blankRawFold #-}---- | Pattern match all cases of the scope functor, and eliminate the adjoints.-blankFold :: Blank g => BlankFold g a r -> g a -> r-blankFold = scopeWFold-{-# INLINE blankFold #-}---- | Lift a value of your left adjoint functor (annotating the tree) into your--- scope functor.-blankLiftAnno :: Blank g => BlankLeft g a -> g a-blankLiftAnno = scopeWLiftAnno-{-# INLINE blankLiftAnno #-}---- | Apply a natural transformation to your left adjoint functor (annotating the tree) to--- change scope functors.-blankHoistAnno :: BlankPair g h => (forall x. BlankLeft g x -> BlankLeft h x) -> g a -> h a-blankHoistAnno = scopeWHoistAnno-{-# INLINE blankHoistAnno #-}---- | Apply a function to the free variables in scope in the context of the left adjoint functor.--- (Allows you to read annotations when fmapping.)-blankMapAnno :: Blank g => (BlankLeft g a -> BlankLeft g b) -> g a -> g b-blankMapAnno = scopeWMapAnno-{-# INLINE blankMapAnno #-}
src/Blanks/LocScope.hs view
@@ -7,34 +7,46 @@   , pattern LocScopeBinder   , pattern LocScopeEmbed   , locScopeLocation-  , locScopeForget+  , locScopeFree+  , locScopeEmbed+  , locScopeFromInnerBinder+  , locScopeBind+  , locScopeBindOpt+  , locScopeLift+  , locScopeInnerBinder+  , locScopeInnerBinder1+  , locScopeAbstract+  , locScopeAbstract1+  , locScopeUnAbstract+  , locScopeUnAbstract1+  , locScopeInstantiate+  , locScopeInstantiate1+  , locScopeApply+  , locScopeApply1+  , locScopeLiftAnno+  , locScopeHoistAnno+  , locScopeMapAnno   ) where -import Blanks.Interface (Blank, BlankFunctor, BlankInfo, BlankLeft, BlankRight, blankBind, blankHoistAnno, blankMapAnno)+import Blanks.Core (BinderScope) import Blanks.Located (Colocated, Located (..), askColocated) import Blanks.NatNewtype (NatNewtype)-import Blanks.Scope (Scope (..))-import Blanks.ScopeW (ScopeW (..))-import Blanks.UnderScope (pattern UnderScopeBinder, pattern UnderScopeBound, pattern UnderScopeEmbed,-                          pattern UnderScopeFree)+import Blanks.ScopeW (ScopeW (..), scopeWAbstract, scopeWAbstract1, scopeWApply, scopeWApply1, scopeWBind,+                      scopeWBindOpt, scopeWEmbed, scopeWFree, scopeWFromInnerBinder, scopeWHoistAnno, scopeWInnerBinder,+                      scopeWInnerBinder1, scopeWInstantiate, scopeWInstantiate1, scopeWLift, scopeWLiftAnno,+                      scopeWMapAnno, scopeWUnAbstract, scopeWUnAbstract1)+import Blanks.Sub (SubError)+import Blanks.Under (pattern UnderScopeBinder, pattern UnderScopeBound, pattern UnderScopeEmbed, pattern UnderScopeFree) import Control.DeepSeq (NFData (..)) import Control.Monad (ap)-import Control.Monad.Identity (Identity (..)) import Control.Monad.Writer (MonadWriter (..))+import Data.Sequence (Seq)  -- | A 'Scope' annotated with some information between constructors.--- See 'Blank' for usage, and see the patterns in this module for easy manipulation--- and inspection. newtype LocScope l n f a = LocScope   { unLocScope :: ScopeW (Located l) n f (LocScope l n f) a   } deriving stock (Functor, Foldable, Traversable) -type instance BlankLeft (LocScope l n f) = Located l-type instance BlankRight (LocScope l n f) = Colocated l-type instance BlankInfo (LocScope l n f) = n-type instance BlankFunctor (LocScope l n f) = f--instance Functor f => Blank (LocScope l n f) instance NatNewtype (ScopeW (Located l) n f (LocScope l n f)) (LocScope l n f)  instance (NFData l, NFData n, NFData a, NFData (f (LocScope l n f a))) => NFData (LocScope l n f a) where@@ -69,14 +81,14 @@  instance (Monoid l, Functor f) => Monad (LocScope l n f) where   return = pure-  s >>= f = blankBind go s where+  s >>= f = locScopeBind go s where     go a = fmap (\l1 -> let LocScope (ScopeW (Located l2 b)) = f a in LocScope (ScopeW (Located (l1 <> l2) b))) askColocated  instance (Monoid l, Functor f) => MonadWriter l (LocScope l n f) where   writer (a, l) = LocScopeFree l a   tell l = LocScopeFree l ()-  listen = blankMapAnno (\(Located l a) -> Located l (a, l))-  pass = blankMapAnno (\(Located l (a, f)) -> Located (f l) a)+  listen = locScopeMapAnno (\(Located l a) -> Located l (a, l))+  pass = locScopeMapAnno (\(Located l (a, f)) -> Located (f l) a)  instance (Eq (f (LocScope l n f a)), Eq l, Eq n, Eq a) => Eq (LocScope l n f a) where   LocScope su == LocScope sv = su == sv@@ -84,6 +96,84 @@ instance (Show (f (LocScope l n f a)), Show l, Show n, Show a) => Show (LocScope l n f a) where   showsPrec d (LocScope (ScopeW tu)) = showString "LocScope " . showsPrec (d+1) tu --- | Forget all the annotations and yield a plain 'Scope'.-locScopeForget :: Functor f => LocScope l n f a -> Scope n f a-locScopeForget = blankHoistAnno (\(Located _ a) -> Identity a)+-- * Interface++locScopeFree :: Functor f => a -> Colocated l (LocScope l n f a)+locScopeFree = scopeWFree+{-# INLINE locScopeFree #-}++locScopeEmbed :: Functor f => f (LocScope l n f a) -> Colocated l (LocScope l n f a)+locScopeEmbed = scopeWEmbed+{-# INLINE locScopeEmbed #-}++locScopeFromInnerBinder :: Functor f => BinderScope n (LocScope l n f a) -> Colocated l (LocScope l n f a)+locScopeFromInnerBinder = scopeWFromInnerBinder+{-# INLINE locScopeFromInnerBinder #-}++locScopeBind :: Functor f => (a -> Colocated l (LocScope l n f b)) -> LocScope l n f a -> LocScope l n f b+locScopeBind = scopeWBind+{-# INLINE locScopeBind #-}++locScopeBindOpt :: Functor f => (a -> Maybe (Colocated l (LocScope l n f a))) -> LocScope l n f a -> LocScope l n f a+locScopeBindOpt = scopeWBindOpt+{-# INLINE locScopeBindOpt #-}++locScopeLift :: Traversable f => f a -> Colocated l (LocScope l n f a)+locScopeLift = scopeWLift+{-# INLINE locScopeLift #-}++locScopeInnerBinder :: (Functor f, Eq a) => n -> Seq a -> LocScope l n f a -> BinderScope n (LocScope l n f a)+locScopeInnerBinder = scopeWInnerBinder+{-# INLINE locScopeInnerBinder #-}++locScopeInnerBinder1 :: (Functor f, Eq a) => n -> a -> LocScope l n f a -> BinderScope n (LocScope l n f a)+locScopeInnerBinder1 = scopeWInnerBinder1+{-# INLINE locScopeInnerBinder1 #-}++locScopeAbstract :: (Functor f, Eq a) => n -> Seq a -> LocScope l n f a -> Colocated l (LocScope l n f a)+locScopeAbstract = scopeWAbstract+{-# INLINE locScopeAbstract #-}++locScopeAbstract1 :: (Functor f, Eq a) => n -> a -> LocScope l n f a -> Colocated l (LocScope l n f a)+locScopeAbstract1 = scopeWAbstract1+{-# INLINE locScopeAbstract1 #-}++locScopeUnAbstract :: Functor f => Seq a -> LocScope l n f a -> LocScope l n f a+locScopeUnAbstract = scopeWUnAbstract+{-# INLINE locScopeUnAbstract #-}++locScopeUnAbstract1 :: Functor f => a -> LocScope l n f a -> LocScope l n f a+locScopeUnAbstract1 = scopeWUnAbstract1+{-# INLINE locScopeUnAbstract1 #-}++locScopeInstantiate :: Functor f => Seq (Colocated l (LocScope l n f a)) -> LocScope l n f a -> LocScope l n f a+locScopeInstantiate = scopeWInstantiate+{-# INLINE locScopeInstantiate #-}++locScopeInstantiate1 :: Functor f => Colocated l (LocScope l n f a) -> LocScope l n f a -> LocScope l n f a+locScopeInstantiate1 = scopeWInstantiate1+{-# INLINE locScopeInstantiate1 #-}++locScopeApply :: Functor f => Seq (Colocated l (LocScope l n f a)) -> LocScope l n f a -> Either SubError (LocScope l n f a)+locScopeApply = scopeWApply+{-# INLINE locScopeApply #-}++locScopeApply1 :: Functor f => Colocated l (LocScope l n f a) -> LocScope l n f a -> Either SubError (LocScope l n f a)+locScopeApply1 = scopeWApply1+{-# INLINE locScopeApply1 #-}++locScopeLiftAnno :: Located l a -> LocScope l n f a+locScopeLiftAnno = scopeWLiftAnno+{-# INLINE locScopeLiftAnno #-}++-- Need an explicit type sig and forall to use this in the hoist below+mapLocatedForall :: (l -> x) -> (forall z. Located l z -> Located x z)+mapLocatedForall f (Located l z) = Located (f l) z++locScopeHoistAnno :: Functor f => (l -> x) -> LocScope l n f a -> LocScope x n f a+locScopeHoistAnno f = scopeWHoistAnno (mapLocatedForall f)+{-# INLINE locScopeHoistAnno #-}++locScopeMapAnno :: Functor f => (Located l a -> Located l b) -> LocScope l n f a -> LocScope l n f b+locScopeMapAnno = scopeWMapAnno+{-# INLINE locScopeMapAnno #-}
src/Blanks/Located.hs view
@@ -22,8 +22,8 @@ -- It's also basically the 'Writer' monad in certain contexts. -- We define a new, non-transforming datatype so we can pattern-match. data Located l a = Located-  { _locatedLoc :: !l-  , _locatedVal :: a+  { locatedLoc :: !l+  , locatedVal :: a   } deriving stock (Eq, Show, Functor, Foldable, Traversable, Generic)     deriving anyclass (NFData) 
src/Blanks/Name.hs view
@@ -14,8 +14,8 @@ -- terms structurally ('Eq') equivalent. data Name n a =   Name-    { _nameKey :: !n-    , _nameValue :: !a+    { nameKey :: !n+    , nameValue :: !a     }   deriving stock (Show, Functor, Foldable, Traversable, Generic)   deriving anyclass (NFData)
src/Blanks/Scope.hs view
@@ -6,30 +6,41 @@   , pattern ScopeFree   , pattern ScopeBinder   , pattern ScopeEmbed+  , scopeWFromInnerBinder+  , scopeBind+  , scopeBindOpt+  , scopeLift+  , scopeInnerBinder+  , scopeInnerBinder1+  , scopeAbstract+  , scopeAbstract1+  , scopeUnAbstract+  , scopeUnAbstract1+  , scopeInstantiate+  , scopeInstantiate1+  , scopeApply+  , scopeApply1   ) where -import Blanks.Interface (Blank, BlankFunctor, BlankInfo, BlankLeft, BlankRight, blankBind, blankFree)+import Blanks.Core (BinderScope) import Blanks.NatNewtype (NatNewtype)-import Blanks.ScopeW (ScopeW (..))-import Blanks.UnderScope (pattern UnderScopeBinder, pattern UnderScopeBound, pattern UnderScopeEmbed,-                          pattern UnderScopeFree)+import Blanks.ScopeW (ScopeW (ScopeW), scopeWAbstract, scopeWAbstract1, scopeWApply, scopeWApply1, scopeWBind,+                      scopeWBindOpt, scopeWFromInnerBinder, scopeWInnerBinder, scopeWInnerBinder1, scopeWInstantiate,+                      scopeWInstantiate1, scopeWLift, scopeWUnAbstract, scopeWUnAbstract1)+import Blanks.Sub (SubError)+import Blanks.Under (pattern UnderScopeBinder, pattern UnderScopeBound, pattern UnderScopeEmbed, pattern UnderScopeFree) import Control.DeepSeq (NFData (..)) import Control.Monad (ap) import Control.Monad.Identity (Identity (..))+import Data.Sequence (Seq)  -- | A simple wrapper for your expression functor that knows how to name-bind.--- See 'Blank' for usage, and see the patterns in this module for easy manipulation--- and inspection.+-- Create free variables is 'pure', bind them with '>>=', and list free variables with folds.+-- See 'LocScope' for a version with additional annotations between layers. newtype Scope n f a = Scope   { unScope :: ScopeW Identity n f (Scope n f) a   } deriving stock (Functor, Foldable, Traversable) -type instance BlankLeft (Scope n f) = Identity-type instance BlankRight (Scope n f) = Identity-type instance BlankInfo (Scope n f) = n-type instance BlankFunctor (Scope n f) = f--instance Functor f => Blank (Scope n f) instance NatNewtype (ScopeW Identity n f (Scope n f)) (Scope n f)  instance (NFData n, NFData a, NFData (f (Scope n f a))) => NFData (Scope n f a) where@@ -50,15 +61,116 @@ {-# COMPLETE ScopeBound, ScopeFree, ScopeBinder, ScopeEmbed #-}  instance Functor f => Applicative (Scope n f) where-  pure = runIdentity . blankFree+  pure = ScopeFree   (<*>) = ap  instance Functor f => Monad (Scope n f) where   return = pure-  s >>= f = blankBind (Identity . f) s+  s >>= f = scopeBind f s  instance (Eq (f (Scope n f a)), Eq n, Eq a) => Eq (Scope n f a) where   Scope su == Scope sv = su == sv  instance (Show (f (Scope n f a)), Show n, Show a) => Show (Scope n f a) where   showsPrec d (Scope (ScopeW tu)) = showString "Scope " . showsPrec (d+1) tu++-- * Interface++scopeFromInnerBinder :: Functor f => BinderScope n (Scope n f a) -> Scope n f a+scopeFromInnerBinder = runIdentity . scopeWFromInnerBinder+{-# INLINE scopeFromInnerBinder #-}++-- | Substitution as a kind of monadic bind.+scopeBind :: Functor f => (a -> Scope n f b) -> Scope n f a -> Scope n f b+scopeBind f = scopeWBind (Identity . f)+{-# INLINE scopeBind #-}++-- | Optional substitution as another kind of monadic bind.+scopeBindOpt :: Functor f => (a -> Maybe (Scope n f a)) -> Scope n f a -> Scope n f a+scopeBindOpt f = scopeWBindOpt (fmap Identity . f)+{-# INLINE scopeBindOpt #-}++-- | Lift an expression functor into the scope functor.+scopeLift :: Traversable f => f a -> Scope n f a+scopeLift = runIdentity . scopeWLift+{-# INLINE scopeLift #-}++scopeInnerBinder :: (Functor f, Eq a) => n -> Seq a -> Scope n f a -> BinderScope n (Scope n f a)+scopeInnerBinder = scopeWInnerBinder+{-# INLINE scopeInnerBinder #-}++scopeInnerBinder1 :: (Functor f, Eq a) => n -> a -> Scope n f a -> BinderScope n (Scope n f a)+scopeInnerBinder1 = scopeWInnerBinder1+{-# INLINE scopeInnerBinder1 #-}++-- | Binds free variables in an expression and returns a binder.+scopeAbstract+  :: (Functor f, Eq a)+  => n+  -- ^ Annotation specific to your expression functor.+  -- Might contain original variable names and types, or might+  -- mark this as a "let" vs a "lambda"+  -> Seq a+  -- ^ Free variables to bind, like the names of function parameters+  -> Scope n f a+  -- ^ The expression to bind in, like the body of a function+  -> Scope n f a+scopeAbstract n ks = runIdentity . scopeWAbstract n ks+{-# INLINE scopeAbstract #-}++-- | 'scopeAbstract' for a single argument.+scopeAbstract1 :: (Functor f, Eq a) => n -> a -> Scope n f a -> Scope n f a+scopeAbstract1 n k = runIdentity . scopeWAbstract1 n k+{-# INLINE scopeAbstract1 #-}++-- | Un-bind free variables in an expression. Basically the inverse of+-- 'scopeAbstract'. Take care to match the arity of the binder! ('scopeApply' is safer.)+scopeUnAbstract+  :: Functor f+  => Seq a+  -- ^ The names of the variables you're freeing+  -> Scope n f a+   -- ^ The expression to substitute in (typically a binder)+  -> Scope n f a+scopeUnAbstract = scopeWUnAbstract+{-# INLINE scopeUnAbstract #-}++-- 'scopeUnAbstract' for a single argument.+scopeUnAbstract1 :: Functor f => a -> Scope n f a -> Scope n f a+scopeUnAbstract1 = scopeWUnAbstract1+{-# INLINE scopeUnAbstract1 #-}++-- | Instantiate the bound variables in an expression with other expressions.+-- Take care to match the arity of the binder! ('scopeApply' is safer.)+scopeInstantiate+  :: Functor f+  => Seq (Scope n f a)+  -- ^ Expressions to substitute in place of bound vars+  -> Scope n f a+  -- ^ The expression to substitute in (typically a binder)+  -> Scope n f a+scopeInstantiate vs = scopeWInstantiate (fmap Identity vs)+{-# INLINE scopeInstantiate #-}++-- | 'scopeInstantiate' for a single argument.+scopeInstantiate1 :: Functor f => Scope n f a -> Scope n f a -> Scope n f a+scopeInstantiate1 v = scopeWInstantiate1 (Identity v)+{-# INLINE scopeInstantiate1 #-}++-- | Instantiates the bound variables in an expression with other expressions.+-- Throws errors on mismatched arity, non binder expression, unbound vars, etc.+-- A version of 'scopeInstantiate' that fails loudly instead of silently!+scopeApply+  :: Functor f+  => Seq (Scope n f a)+  -- ^ Expressions to substitute in place of bound vars+  -> Scope n f a+  -- ^ The binder expression to substitute in+  -> Either SubError (Scope n f a)+scopeApply vs = scopeWApply (fmap Identity vs)+{-# INLINE scopeApply #-}++-- | 'scopeApply' for a single argument.+scopeApply1 :: Functor f => Scope n f a -> Scope n f a -> Either SubError (Scope n f a)+scopeApply1 v = scopeWApply1 (Identity v)+{-# INLINE scopeApply1 #-}
src/Blanks/ScopeW.hs view
@@ -1,31 +1,35 @@ {-# LANGUAGE UndecidableInstances #-} --- | Internals. You'd need to newtype 'ScopeW' to implement your own 'Blank'.+-- | Internals. module Blanks.ScopeW-  ( ScopeC+  ( ScopeWC   , ScopeW (..)-  , ScopeWRawFold-  , ScopeWFold   , scopeWFree   , scopeWEmbed+  , scopeWFromInnerBinder+  , scopeWInnerBinder+  , scopeWInnerBinder1   , scopeWAbstract+  , scopeWAbstract1   , scopeWUnAbstract+  , scopeWUnAbstract1   , scopeWInstantiate+  , scopeWInstantiate1   , scopeWApply+  , scopeWApply1   , scopeWBind   , scopeWBindOpt   , scopeWLift-  , scopeWRawFold-  , scopeWFold   , scopeWLiftAnno   , scopeWHoistAnno   , scopeWMapAnno   ) where +import Blanks.Core (BinderScope (..)) import Blanks.NatNewtype (NatNewtype, natNewtypeFrom, natNewtypeTo) import Blanks.Sub (SubError (..))-import Blanks.UnderScope (UnderScope, pattern UnderScopeBinder, pattern UnderScopeBound, pattern UnderScopeEmbed,-                          UnderScopeFold, pattern UnderScopeFree, underScopeFold, underScopeShift)+import Blanks.Under (UnderScope (..), pattern UnderScopeBinder, pattern UnderScopeBound, pattern UnderScopeEmbed,+                     pattern UnderScopeFree, underScopeShift) import Control.DeepSeq (NFData (..)) import Data.Bifoldable (bifoldr) import Data.Bifunctor (bimap, first)@@ -37,11 +41,16 @@  -- * ScopeW, patterns, and instances +-- | The core internal scope type. (The "w" comes from "wrapper".)+-- We wrap up an 'UnderScope' in some functor and demand that we+-- unwrap it in an adjoint context. In the first case, these functors will be+-- 'Identity', yielding the 'Scope' newtype. In the second case, these+-- functors will be 'Located' and 'Colocated', yielding the 'LocScope' newtype. newtype ScopeW t n f g a = ScopeW   { unScopeW :: t (UnderScope n f (g a) a)   } -instance NFData (t (UnderScope n f (g a) a) )=> NFData (ScopeW t n f g a) where+instance NFData (t (UnderScope n f (g a) a)) => NFData (ScopeW t n f g a) where   rnf (ScopeW tu) = seq (rnf tu) ()  instance Eq (t (UnderScope n f (g a) a)) => Eq (ScopeW t n f g a) where@@ -59,43 +68,51 @@ instance (Traversable t, Traversable f, Traversable g) => Traversable (ScopeW t n f g) where   traverse f (ScopeW tu) = fmap ScopeW (traverse (bitraverse (traverse f) f) tu) -type ScopeC t u n f g = (Adjunction t u, Applicative u, Functor f, NatNewtype (ScopeW t n f g) g)+type ScopeWC t u n f g = (Adjunction t u, Applicative u, Functor f, NatNewtype (ScopeW t n f g) g)  -- * Smart constructors, shift, and bind -scopeWMod :: ScopeC t u n f g => (UnderScope n f (g a) a -> u x) -> g a -> x+scopeWMod :: ScopeWC t u n f g => (UnderScope n f (g a) a -> u x) -> g a -> x scopeWMod f = rightAdjunct f . unScopeW . natNewtypeFrom+{-# INLINE scopeWMod #-} -scopeWModOpt :: ScopeC t u n f g => (UnderScope n f (g a) a -> Maybe (u (g a))) -> g a -> g a+scopeWModOpt :: ScopeWC t u n f g => (UnderScope n f (g a) a -> Maybe (u (g a))) -> g a -> g a scopeWModOpt f s = rightAdjunct (fromMaybe (pure s) . f) (unScopeW (natNewtypeFrom s))+{-# INLINE scopeWModOpt #-} -scopeWModM :: (ScopeC t u n f g, Traversable m) => (UnderScope n f (g a) a -> m (u x)) -> g a -> m x+scopeWModM :: (ScopeWC t u n f g, Traversable m) => (UnderScope n f (g a) a -> m (u x)) -> g a -> m x scopeWModM f = rightAdjunct (sequenceA . f) . unScopeW . natNewtypeFrom+{-# INLINE scopeWModM #-} -scopeWBound :: ScopeC t u n f g => Int -> u (g a)+scopeWBound :: ScopeWC t u n f g => Int -> u (g a) scopeWBound b = fmap (natNewtypeTo . ScopeW) (unit (UnderScopeBound b)) -scopeWFree :: ScopeC t u n f g => a -> u (g a)+scopeWFree :: ScopeWC t u n f g => a -> u (g a) scopeWFree a = fmap (natNewtypeTo . ScopeW) (unit (UnderScopeFree a)) -scopeWShift :: ScopeC t u n f g => Int -> g a -> g a+scopeWShift :: ScopeWC t u n f g => Int -> g a -> g a scopeWShift = scopeWShiftN 0+{-# INLINE scopeWShift #-} -scopeWShiftN :: ScopeC t u n f g => Int -> Int -> g a -> g a+scopeWShiftN :: ScopeWC t u n f g => Int -> Int -> g a -> g a scopeWShiftN c d e =   let ScopeW tu = natNewtypeFrom e   in natNewtypeTo (ScopeW (fmap (underScopeShift scopeWShiftN c d) tu)) -scopeWBinder :: ScopeC t u n f g => Int -> n -> g a -> u (g a)+scopeWBinder :: ScopeWC t u n f g => Int -> n -> g a -> u (g a) scopeWBinder r n e = fmap (natNewtypeTo . ScopeW) (unit (UnderScopeBinder r n e)) -scopeWEmbed :: ScopeC t u n f g => f (g a) -> u (g a)+scopeWFromInnerBinder :: ScopeWC t u n f g => BinderScope n (g a) -> u (g a)+scopeWFromInnerBinder b = fmap (natNewtypeTo . ScopeW) (unit (UnderBinderScope b))++scopeWEmbed :: ScopeWC t u n f g => f (g a) -> u (g a) scopeWEmbed fe = fmap (natNewtypeTo . ScopeW) (unit (UnderScopeEmbed fe)) -scopeWBind :: ScopeC t u n f g => (a -> u (g b)) -> g a -> g b+scopeWBind :: ScopeWC t u n f g => (a -> u (g b)) -> g a -> g b scopeWBind f = scopeWBindN f 0+{-# INLINE scopeWBind #-} -scopeWBindN :: ScopeC t u n f g => (a -> u (g b)) -> Int -> g a -> g b+scopeWBindN :: ScopeWC t u n f g => (a -> u (g b)) -> Int -> g a -> g b scopeWBindN f = scopeWMod . go where   go i us =     case us of@@ -104,10 +121,11 @@       UnderScopeBinder r x e -> scopeWBinder r x (scopeWBindN f (i + r) e)       UnderScopeEmbed fe -> scopeWEmbed (fmap (scopeWBindN f i) fe) -scopeWBindOpt :: ScopeC t u n f g => (a -> Maybe (u (g a))) -> g a -> g a+scopeWBindOpt :: ScopeWC t u n f g => (a -> Maybe (u (g a))) -> g a -> g a scopeWBindOpt f = scopeWBindOptN f 0+{-# INLINE scopeWBindOpt #-} -scopeWBindOptN :: ScopeC t u n f g => (a -> Maybe (u (g a))) -> Int -> g a -> g a+scopeWBindOptN :: ScopeWC t u n f g => (a -> Maybe (u (g a))) -> Int -> g a -> g a scopeWBindOptN f = scopeWModOpt . go where   go i us =     case us of@@ -116,29 +134,48 @@       UnderScopeBinder r x e -> Just (scopeWBinder r x (scopeWBindOptN f (i + r) e))       UnderScopeEmbed fe -> Just (scopeWEmbed (fmap (scopeWBindOptN f i) fe)) -scopeWLift :: (ScopeC t u n f g, Monad u, Traversable f) => f a -> u (g a)+scopeWLift :: (ScopeWC t u n f g, Monad u, Traversable f) => f a -> u (g a) scopeWLift fa = traverse scopeWFree fa >>= scopeWEmbed  -- * Abstraction -subScopeWAbstract :: (ScopeC t u n f g, Eq a) => Int -> n -> Seq a -> g a -> u (g a)-subScopeWAbstract r n ks e =-  let f = fmap scopeWBound . flip Seq.elemIndexL ks-      e' = scopeWBindOpt f e-  in scopeWBinder r n e'--scopeWAbstract :: (ScopeC t u n f g, Eq a) => n -> Seq a -> g a -> u (g a)-scopeWAbstract n ks =+scopeWInnerBinder :: (ScopeWC t u n f g, Eq a) => n -> Seq a -> g a -> BinderScope n (g a)+scopeWInnerBinder n ks e =   let r = Seq.length ks-  in subScopeWAbstract r n ks . scopeWShift r+      e' = scopeWShift r e+      f = fmap scopeWBound . flip Seq.elemIndexL ks+      e'' = scopeWBindOpt f e'+  in BinderScope r n e'' -scopeWUnAbstract :: ScopeC t u n f g => Seq a -> g a -> g a+scopeWInnerBinder1 :: (ScopeWC t u n f g, Eq a) => n -> a -> g a -> BinderScope n (g a)+scopeWInnerBinder1 n = scopeWInnerBinder n . Seq.singleton+{-# INLINE scopeWInnerBinder1 #-}++scopeWAbstract :: (ScopeWC t u n f g, Eq a) => n -> Seq a -> g a -> u (g a)+scopeWAbstract n ks e = scopeWFromInnerBinder (scopeWInnerBinder n ks e)+{-# INLINE scopeWAbstract #-}++scopeWAbstract1 :: (ScopeWC t u n f g, Eq a) => n -> a -> g a -> u (g a)+scopeWAbstract1 n = scopeWAbstract n . Seq.singleton+{-# INLINE scopeWAbstract1 #-}++scopeWUnAbstract :: ScopeWC t u n f g => Seq a -> g a -> g a scopeWUnAbstract ks = scopeWInstantiate (fmap scopeWFree ks)+{-# INLINE scopeWUnAbstract #-} -scopeWInstantiate :: ScopeC t u n f g => Seq (u (g a)) -> g a -> g a+scopeWUnAbstract1 :: ScopeWC t u n f g => a -> g a -> g a+scopeWUnAbstract1 = scopeWUnAbstract . Seq.singleton+{-# INLINE scopeWUnAbstract1 #-}++scopeWInstantiate :: ScopeWC t u n f g => Seq (u (g a)) -> g a -> g a scopeWInstantiate = scopeWInstantiateN 0+{-# INLINE scopeWInstantiate #-} -scopeWInstantiateN :: ScopeC t u n f g => Int -> Seq (u (g a)) -> g a -> g a+scopeWInstantiate1 :: ScopeWC t u n f g => u (g a) -> g a -> g a+scopeWInstantiate1 = scopeWInstantiate . Seq.singleton+{-# INLINE scopeWInstantiate1 #-}++scopeWInstantiateN :: ScopeWC t u n f g => Int -> Seq (u (g a)) -> g a -> g a scopeWInstantiateN h vs = scopeWModOpt (go h) where   go i us =     case us of@@ -150,7 +187,7 @@         in Just (scopeWBinder r n e')       UnderScopeEmbed fe -> Just (scopeWEmbed (fmap (scopeWInstantiateN i vs) fe)) -scopeWApply :: ScopeC t u n f g => Seq (u (g a)) -> g a -> Either SubError (g a)+scopeWApply :: ScopeWC t u n f g => Seq (u (g a)) -> g a -> Either SubError (g a) scopeWApply vs = scopeWModM go where   go us =     case us of@@ -161,16 +198,9 @@               else Left (ApplyError len r)       _ -> Left NonBinderError --- * Folds--type ScopeWRawFold n f g a r = UnderScopeFold n f (g a) a r-type ScopeWFold u n f g a r = ScopeWRawFold n f g a (u r)--scopeWRawFold :: (NatNewtype (ScopeW t n f g) g, Functor t) => ScopeWRawFold n f g a r -> g a -> t r-scopeWRawFold usf = fmap (underScopeFold usf) . unScopeW . natNewtypeFrom--scopeWFold :: (NatNewtype (ScopeW t n f g) g, Adjunction t u) => ScopeWFold u n f g a r -> g a -> r-scopeWFold usf = counit . scopeWRawFold usf+scopeWApply1 :: ScopeWC t u n f g => u (g a) -> g a -> Either SubError (g a)+scopeWApply1 = scopeWApply . Seq.singleton+{-# INLINE scopeWApply1 #-}  -- * Annotation functions @@ -183,7 +213,7 @@       s = ScopeW (nat (fmap (first (scopeWHoistAnno nat)) tu))   in natNewtypeTo s -scopeWMapAnno :: ScopeC t u n f g => (t a -> t b) -> g a -> g b+scopeWMapAnno :: ScopeWC t u n f g => (t a -> t b) -> g a -> g b scopeWMapAnno f = scopeWMod go where   go us = case us of     UnderScopeBound b -> scopeWBound b
+ src/Blanks/Split.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE UndecidableInstances #-}++module Blanks.Split+  ( BinderId (..)+  , SplitFunctor (..)+  , SplitBinder (..)+  , SplitResult (..)+  , splitLocScope+  ) where++import Blanks.Core (BinderScope (..))+import Blanks.LocScope (LocScope, pattern LocScopeBinder, pattern LocScopeBound, pattern LocScopeEmbed,+                        pattern LocScopeFree)+import Blanks.Tracked (Tracked (..), WithTracked (..), mkTrackedBound, mkTrackedFree)+import Control.DeepSeq (NFData (..))+import Control.Monad.State (State, gets, modify', runState)+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map+import Data.Sequence (Seq)+import qualified Data.Sequence as Seq+import Data.Set (Set)+import qualified Data.Set as Set+import GHC.Generics (Generic)++data Stream x = Stream !x (Stream x)++enumStreamFrom :: Enum e => e -> Stream e+enumStreamFrom e = Stream e (enumStreamFrom (succ e))++enumStream :: Enum e => Stream e+enumStream = enumStreamFrom (toEnum 0)++newtype BinderId = BinderId { unBinderId :: Int }+  deriving stock (Eq, Show, Ord)+  deriving newtype (Enum, NFData, Num)++data SplitFunctor f a =+    SplitFunctorBase !(f a)+  | SplitFunctorClosure !BinderId !(Seq Int)+  deriving stock (Eq, Show, Generic, Functor, Foldable, Traversable)+  deriving anyclass (NFData)++data SplitBinder l n f a = SplitBinder+  { splitBinderClosureArity :: !Int+  , splitBinderFree :: !(Set a)+  , splitBinderScope :: !(BinderScope n (LocScope l n (SplitFunctor f) a))+  } deriving stock (Generic)++instance (Eq l, Eq n, Eq a, Eq (f (LocScope l n (SplitFunctor f) a))) => Eq (SplitBinder l n f a) where+  SplitBinder a1 f1 s1 == SplitBinder a2 f2 s2 = a1 == a2 && f1 == f2 && s1 == s2++instance (Show l, Show n, Show a, Show (f (LocScope l n (SplitFunctor f) a))) => Show (SplitBinder l n f a) where+  showsPrec d (SplitBinder a f s) = showString "SplitBinder " . showsPrec (d+1) a . showChar ' ' . showsPrec (d+1) f . showChar ' ' . showsPrec (d+1) s++instance (NFData l, NFData n, NFData a, NFData (f (LocScope l n (SplitFunctor f) a))) => NFData (SplitBinder l n f a) where+  rnf (SplitBinder a f s) = seq (rnf a) (seq (rnf f) (rnf s))++data SplitState l n f a = SplitState+  { splitStateStream :: !(Stream BinderId)+  , splitStateBinders :: !(Map BinderId (SplitBinder l n f a))+  }++initSplitState :: SplitState l n f a+initSplitState = SplitState enumStream Map.empty++getNextBinderId :: State (SplitState l n f a) BinderId+getNextBinderId = do+  st <- gets splitStateStream+  let Stream hd tl = st+  modify' (\ss -> ss { splitStateStream = tl })+  pure hd++insertBinder :: BinderId -> SplitBinder l n f a -> State (SplitState l n f a) ()+insertBinder bid lb = modify' (\ss -> ss { splitStateBinders = Map.insert bid lb (splitStateBinders ss) })++remapBound :: Int -> Set Int -> Int -> Int+remapBound r bs b = maybe b (+ r) (Set.lookupIndex b bs)++splitLocScopeInner :: (Traversable f, Ord a) => Int -> Set Int -> LocScope (WithTracked a l) n f a -> State (SplitState l n f a) (Tracked a, LocScope l n (SplitFunctor f) a)+splitLocScopeInner r bs ls =+  case ls of+    LocScopeBound (WithTracked _ l) b ->+      let !b' = remapBound r bs b+      in pure (mkTrackedBound b', LocScopeBound l b')+    LocScopeFree (WithTracked _ l) a ->+      pure (mkTrackedFree a, LocScopeFree l a)+    LocScopeEmbed (WithTracked _ l) fe -> fmap (\fx -> let (!t, !fe') = sequence fx in (t, LocScopeEmbed l (SplitFunctorBase fe'))) (traverse (splitLocScopeInner r bs) fe)+    LocScopeBinder (WithTracked (Tracked fv bv) l) x n e -> do+      bid <- getNextBinderId+      let bs' = Set.mapMonotonic (+ r) bv+      (_, e') <- splitLocScopeInner x bs' e+      let lb = SplitBinder (Set.size bs') fv (BinderScope x n e')+      insertBinder bid lb+      let ss = Seq.fromList (Set.toList bv)+      pure (Tracked Set.empty bv, LocScopeEmbed l (SplitFunctorClosure bid ss))++data SplitResult l n f a = SplitResult+  { splitResultTracked :: !(Tracked a)+  , splitResultScope :: !(LocScope l n (SplitFunctor f) a)+  , splitResultBinders :: !(Map BinderId (SplitBinder l n f a))+  }++splitLocScope :: (Traversable f, Ord a) => LocScope (WithTracked a l) n f a -> SplitResult l n f a+splitLocScope s =+  let ((!t, !s'), !ss) = runState (splitLocScopeInner 0 Set.empty s) initSplitState+  in SplitResult t s' (splitStateBinders ss)
+ src/Blanks/Tracked.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE DeriveAnyClass #-}++-- | Utilities for gathering and caching sets of free variables.+module Blanks.Tracked+  ( Tracked (..)+  , mkTrackedFree+  , mkTrackedBound+  , shiftTracked+  , WithTracked (..)+  , forgetTrackedScope+  , trackScope+  , trackScopeSimple+  ) where++import Blanks.Conversion (scopeAnno)+import Blanks.LocScope (LocScope, pattern LocScopeBinder, pattern LocScopeBound, pattern LocScopeEmbed,+                        pattern LocScopeFree, locScopeHoistAnno)+import Blanks.Scope (Scope)+import Control.DeepSeq (NFData)+import Data.Set (Set)+import qualified Data.Set as Set+import GHC.Generics (Generic)++data Tracked a = Tracked+  { trackedFree :: !(Set a)+  , trackedBound :: !(Set Int)+  } deriving stock (Eq, Show, Generic)+    deriving anyclass (NFData)++mkTrackedFree :: a -> Tracked a+mkTrackedFree a = Tracked (Set.singleton a) Set.empty++mkTrackedBound :: Int -> Tracked a+mkTrackedBound b = Tracked Set.empty (Set.singleton b)++shiftTracked :: Int -> Tracked a -> Tracked a+shiftTracked i t@(Tracked f b) =+  if Set.null b+    then t+    else+      let !b' = if Set.findMax b < i then Set.empty else Set.dropWhileAntitone (< 0) (Set.mapMonotonic (\x -> x - i) b)+      in Tracked f b'++instance Ord a => Semigroup (Tracked a) where+  Tracked f1 b1 <> Tracked f2 b2 = Tracked (Set.union f1 f2) (Set.union b1 b2)++instance Ord a => Monoid (Tracked a) where+  mempty = Tracked Set.empty Set.empty+  mappend = (<>)++data WithTracked a l = WithTracked+  { withTrackedState :: !(Tracked a)+  , withTrackedEnv :: !l+  } deriving stock (Eq, Show, Generic, Functor, Foldable, Traversable)+    deriving anyclass (NFData)++forgetTrackedScope :: Functor f => LocScope (WithTracked a l) n f z -> LocScope l n f z+forgetTrackedScope = locScopeHoistAnno withTrackedEnv++trackScopeInner :: (Traversable f, Ord a) => LocScope l n f a -> (Tracked a, LocScope (WithTracked a l) n f a)+trackScopeInner s =+  case s of+    LocScopeBound l b ->+      let !t = Tracked Set.empty (Set.singleton b)+          !m = WithTracked t l+      in (t, LocScopeBound m b)+    LocScopeFree l a ->+      let !t = Tracked (Set.singleton a) Set.empty+          !m = WithTracked t l+      in (t, LocScopeFree m a)+    LocScopeBinder l n i e ->+      let !(t0, y) = trackScopeInner e+          !t = shiftTracked n t0+          !m = WithTracked t l+      in (t, LocScopeBinder m n i y)+    LocScopeEmbed l fe ->+      let (!t, !fy) = traverse trackScopeInner fe+          !m = WithTracked t l+      in (t, LocScopeEmbed m fy)++trackScope :: (Traversable f, Ord a) => LocScope l n f a -> LocScope (WithTracked a l) n f a+trackScope = snd . trackScopeInner++trackScopeSimple :: (Traversable f, Ord a) => Scope n f a -> LocScope (Tracked a) n f a+trackScopeSimple = locScopeHoistAnno withTrackedState . trackScope . scopeAnno ()
+ src/Blanks/Under.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE DeriveAnyClass #-}++-- | Internals.+module Blanks.Under+  ( UnderScope (..)+  , pattern UnderScopeBound+  , pattern UnderScopeFree+  , pattern UnderScopeBinder+  , pattern UnderScopeEmbed+  , underScopeShift+  ) where++import Blanks.Core (BinderScope (..), BoundScope (..), EmbedScope (..), FreeScope (..))+import Control.DeepSeq (NFData)+import Data.Bifoldable (Bifoldable (..))+import Data.Bifunctor (Bifunctor (..))+import Data.Bitraversable (Bitraversable (..))+import GHC.Generics (Generic)++data UnderScope n f e a+  = UnderBoundScope !BoundScope+  | UnderFreeScope !(FreeScope a)+  | UnderBinderScope !(BinderScope n e)+  | UnderEmbedScope !(EmbedScope f e)+  deriving stock (Eq, Show, Functor, Generic)+  deriving anyclass (NFData)++pattern UnderScopeBound :: Int -> UnderScope n f e a+pattern UnderScopeBound i = UnderBoundScope (BoundScope i)++pattern UnderScopeFree :: a -> UnderScope n f e a+pattern UnderScopeFree a = UnderFreeScope (FreeScope a)++pattern UnderScopeBinder :: Int -> n -> e -> UnderScope n f e a+pattern UnderScopeBinder i n e = UnderBinderScope (BinderScope i n e)++pattern UnderScopeEmbed :: f e -> UnderScope n f e a+pattern UnderScopeEmbed fe = UnderEmbedScope (EmbedScope fe)++{-# COMPLETE UnderScopeBound, UnderScopeFree, UnderScopeBinder, UnderScopeEmbed #-}++instance Functor f => Bifunctor (UnderScope n f) where+  bimap _ _ (UnderBoundScope (BoundScope b)) = UnderBoundScope (BoundScope b)+  bimap _ g (UnderFreeScope (FreeScope a)) = UnderFreeScope (FreeScope (g a))+  bimap f _ (UnderBinderScope (BinderScope i x e)) = UnderBinderScope (BinderScope i x (f e))+  bimap f _ (UnderEmbedScope (EmbedScope fe)) = UnderEmbedScope (EmbedScope (fmap f fe))++instance Foldable f => Bifoldable (UnderScope n f) where+  bifoldr _ _ z (UnderBoundScope _) = z+  bifoldr _ g z (UnderFreeScope (FreeScope a)) = g a z+  bifoldr f _ z (UnderBinderScope (BinderScope _ _ e)) = f e z+  bifoldr f _ z (UnderEmbedScope (EmbedScope fe)) = foldr f z fe++instance Traversable f => Bitraversable (UnderScope n f) where+  bitraverse _ _ (UnderBoundScope (BoundScope b)) = pure (UnderBoundScope (BoundScope b))+  bitraverse _ g (UnderFreeScope (FreeScope a)) = fmap (UnderFreeScope . FreeScope) (g a)+  bitraverse f _ (UnderBinderScope (BinderScope i x e)) = fmap (UnderBinderScope . BinderScope i x) (f e)+  bitraverse f _ (UnderEmbedScope (EmbedScope fe)) = fmap (UnderEmbedScope . EmbedScope) (traverse f fe)++underScopeShift :: Functor f => (Int -> Int -> e -> e) -> Int -> Int -> UnderScope n f e a -> UnderScope n f e a+underScopeShift recShift c d us =+  case us of+    UnderBoundScope (BoundScope b) ->+      if b < c+        then us+        else UnderBoundScope (BoundScope (b + d))+    UnderFreeScope _ -> us+    UnderBinderScope (BinderScope i x e) -> UnderBinderScope (BinderScope i x (recShift (c + i) d e))+    UnderEmbedScope (EmbedScope fe) -> UnderEmbedScope (EmbedScope (fmap (recShift c d) fe))
− src/Blanks/UnderScope.hs
@@ -1,119 +0,0 @@-{-# LANGUAGE DeriveAnyClass #-}---- | Internals. You will probably never need these.-module Blanks.UnderScope-  ( BinderScope (..)-  , BoundScope (..)-  , EmbedScope (..)-  , FreeScope (..)-  , UnderScope (..)-  , UnderScopeFold (..)-  , pattern UnderScopeBound-  , pattern UnderScopeFree-  , pattern UnderScopeBinder-  , pattern UnderScopeEmbed-  , underScopeFold-  , underScopeShift-  ) where--import Control.DeepSeq (NFData)-import Data.Bifoldable (Bifoldable (..))-import Data.Bifunctor (Bifunctor (..))-import Data.Bitraversable (Bitraversable (..))-import GHC.Generics (Generic)--newtype BoundScope =-  BoundScope-    { unBoundScope :: Int-    }-  deriving newtype (Eq, Show, NFData)--newtype FreeScope a =-  FreeScope-    { unFreeScope :: a-    }-  deriving stock (Eq, Show, Functor, Foldable, Traversable)-  deriving newtype (NFData)--data BinderScope n e =-  BinderScope-    { binderScopeArity :: !Int-    , binderScopeInfo :: !n-    , binderScopeBody :: e-    }-  deriving stock (Eq, Show, Functor, Foldable, Traversable, Generic)-  deriving anyclass (NFData)--newtype EmbedScope f e =-  EmbedScope-    { unEmbedScope :: f e-    }-  deriving newtype (Eq, Show, Functor, NFData)--data UnderScope n f e a-  = UnderBoundScope !BoundScope-  | UnderFreeScope !(FreeScope a)-  | UnderBinderScope !(BinderScope n e)-  | UnderEmbedScope !(EmbedScope f e)-  deriving stock (Eq, Show, Functor, Generic)-  deriving anyclass (NFData)--pattern UnderScopeBound :: Int -> UnderScope n f e a-pattern UnderScopeBound i = UnderBoundScope (BoundScope i)--pattern UnderScopeFree :: a -> UnderScope n f e a-pattern UnderScopeFree a = UnderFreeScope (FreeScope a)--pattern UnderScopeBinder :: Int -> n -> e -> UnderScope n f e a-pattern UnderScopeBinder i n e = UnderBinderScope (BinderScope i n e)--pattern UnderScopeEmbed :: f e -> UnderScope n f e a-pattern UnderScopeEmbed fe = UnderEmbedScope (EmbedScope fe)--{-# COMPLETE UnderScopeBound, UnderScopeFree, UnderScopeBinder, UnderScopeEmbed #-}--instance Functor f => Bifunctor (UnderScope n f) where-  bimap _ _ (UnderBoundScope (BoundScope b)) = UnderBoundScope (BoundScope b)-  bimap _ g (UnderFreeScope (FreeScope a)) = UnderFreeScope (FreeScope (g a))-  bimap f _ (UnderBinderScope (BinderScope i x e)) = UnderBinderScope (BinderScope i x (f e))-  bimap f _ (UnderEmbedScope (EmbedScope fe)) = UnderEmbedScope (EmbedScope (fmap f fe))--instance Foldable f => Bifoldable (UnderScope n f) where-  bifoldr _ _ z (UnderBoundScope _) = z-  bifoldr _ g z (UnderFreeScope (FreeScope a)) = g a z-  bifoldr f _ z (UnderBinderScope (BinderScope _ _ e)) = f e z-  bifoldr f _ z (UnderEmbedScope (EmbedScope fe)) = foldr f z fe--instance Traversable f => Bitraversable (UnderScope n f) where-  bitraverse _ _ (UnderBoundScope (BoundScope b)) = pure (UnderBoundScope (BoundScope b))-  bitraverse _ g (UnderFreeScope (FreeScope a)) = fmap (UnderFreeScope . FreeScope) (g a)-  bitraverse f _ (UnderBinderScope (BinderScope i x e)) = fmap (UnderBinderScope . BinderScope i x) (f e)-  bitraverse f _ (UnderEmbedScope (EmbedScope fe)) = fmap (UnderEmbedScope . EmbedScope) (traverse f fe)--underScopeShift :: Functor f => (Int -> Int -> e -> e) -> Int -> Int -> UnderScope n f e a -> UnderScope n f e a-underScopeShift recShift c d us =-  case us of-    UnderBoundScope (BoundScope b) ->-      if b < c-        then us-        else UnderBoundScope (BoundScope (b + d))-    UnderFreeScope _ -> us-    UnderBinderScope (BinderScope i x e) -> UnderBinderScope (BinderScope i x (recShift (c + i) d e))-    UnderEmbedScope (EmbedScope fe) -> UnderEmbedScope (EmbedScope (fmap (recShift c d) fe))--data UnderScopeFold n f e a r =-  UnderScopeFold-    { usfBound :: BoundScope -> r-    , usfFree :: FreeScope a -> r-    , usfBinder :: BinderScope n e -> r-    , usfEmbed :: EmbedScope f e -> r-    }-  deriving (Functor)--underScopeFold :: UnderScopeFold n f e a r -> UnderScope n f e a -> r-underScopeFold (UnderScopeFold bound free binder embed) us =-  case us of-    UnderBoundScope x -> bound x-    UnderFreeScope x -> free x-    UnderBinderScope x -> binder x-    UnderEmbedScope x -> embed x
test/Main.hs view
@@ -2,9 +2,11 @@   ( main   ) where -import Test.Blanks.LocScopeTest (testLocScope)+import Test.Blanks.ExpTest (testExp) import Test.Blanks.ScopeTest (testScope)+import Test.Blanks.SplitTest (testSplit)+import Test.Blanks.TrackedTest (testTracked) import Test.Tasty (defaultMain, testGroup)  main :: IO ()-main = defaultMain (testGroup "Blanks" [testScope, testLocScope])+main = defaultMain (testGroup "Blanks" [testScope, testTracked, testExp, testSplit])
+ test/Test/Blanks/Exp.hs view
@@ -0,0 +1,254 @@+{-# LANGUAGE DeriveAnyClass #-}++module Test.Blanks.Exp+  ( Ident (..)+  , CExp (..)+  , cexpLoc+  , CDecl (..)+  , declKeywords+  , expKeywords+  , cexpParser+  , runCExpParser+  , cdeclParser+  , runCDeclParser+  , Exp (..)+  , ExpScope+  , DeclScope+  , ExpLocScope+  , DeclLocScope+  , declLocScopeForget+  , declScopeAnno+  , expToNameless+  , expToNamed+  , declToNameless+  , declToNamed+  ) where++import Blanks (LocScope, pattern LocScopeBinder, pattern LocScopeBound, pattern LocScopeEmbed, pattern LocScopeFree,+               Located (..), NameOnly, pattern NameOnly, Scope, locScopeAbstract1, locScopeForget, locScopeUnAbstract1,+               runColocated, scopeAnno)+import Control.DeepSeq (NFData)+import Control.Monad (when)+import Data.Set (Set)+import qualified Data.Set as Set+import GHC.Generics (Generic)+import Test.Blanks.Parsing++-- A newtype indicating an identifier in our language+newtype Ident = Ident { unIdent :: String } deriving newtype (Eq, Show, Ord, NFData)++-- The type of concrete expressions, labeled with source location+data CExp l =+    CExpBool !l !Bool+  | CExpInt !l !Int+  | CExpApp !l !(CExp l) !(CExp l)+  | CExpAdd !l !(CExp l) !(CExp l)+  | CExpIf !l !(CExp l) !(CExp l) !(CExp l)+  | CExpIsZero !l !(CExp l)+  | CExpVar !l !Ident+  | CExpAbs !l !Ident !(CExp l)+  | CExpAsc !l !(CExp l) !(CExp l)+  | CExpTyInt !l+  | CExpTyBool !l+  | CExpTyFun !l !(CExp l) !(CExp l)+  deriving stock (Eq, Show, Generic)+  deriving anyclass (NFData)++-- Extracts the location from a concrete expression+cexpLoc :: CExp l -> l+cexpLoc ce =+  case ce of+    CExpBool l _ -> l+    CExpInt l _ -> l+    CExpApp l _ _ -> l+    CExpAdd l _ _ -> l+    CExpIf l _ _ _ -> l+    CExpIsZero l _ -> l+    CExpVar l _ -> l+    CExpAbs l _ _ -> l+    CExpAsc l _ _ -> l+    CExpTyInt l -> l+    CExpTyBool l -> l+    CExpTyFun l _ _ -> l++expKeywords :: Set Ident+expKeywords = Set.fromList $ fmap Ident+  [ "#t"+  , "#f"+  , "+"+  , "if"+  , "zero?"+  , ":"+  , "lambda"+  , "int"+  , "bool"+  , "->"+  ]++declKeywords :: Set Ident+declKeywords = Set.fromList $ fmap Ident+  [ "declare"+  , "define"+  ]++nonKeywordParser :: Parser Ident+nonKeywordParser = do+  rawIdent <- identifier+  let ident = Ident rawIdent+  when (Set.member ident expKeywords) (fail ("Parsed exp keyword: " <> rawIdent))+  when (Set.member ident declKeywords) (fail ("Parsed decl keyword: " <> rawIdent))+  pure ident++-- Parses a concrete expression from a string+cexpParser :: Parser (CExp SourceSpan)+cexpParser = result where+  result = branch+    [ trueParser+    , falseParser+    , intParser+    , addParser+    , ifParser+    , isZeroParser+    , absParser+    , appParser+    , ascParser+    , tyBoolParser+    , tyIntParser+    , tyFunParser+    , varParser+    ]++  trueParser = around (const . flip CExpBool True) (symbol "#t")++  falseParser = around (const . flip CExpBool False) (symbol "#f")++  intParser = around CExpInt signed++  addParser = around2 CExpAdd (parens (symbol "+" *> double cexpParser))++  ifParser = around3 CExpIf (parens (symbol "if" *> triple cexpParser))++  isZeroParser = around CExpIsZero (parens (symbol "zero?" *> cexpParser))++  absParser = around2 CExpAbs $ parens $ do+    _ <- symbol "lambda"+    n <- parens nonKeywordParser+    b <- cexpParser+    pure (n, b)++  appParser = around2 CExpApp (parens (double cexpParser))++  ascParser = around2 CExpAsc (parens (symbol ":" *> double cexpParser))++  tyBoolParser = around (const . CExpTyBool) (symbol "bool")++  tyIntParser = around (const . CExpTyInt) (symbol "int")++  tyFunParser = around2 (CExpTyFun) (parens (symbol "->" *> double cexpParser))++  varParser = around CExpVar nonKeywordParser++runCExpParser :: String -> IO (CExp SourceSpan)+runCExpParser = runParserIO cexpParser++data Level =+    LevelTerm+  | LevelType+  deriving stock (Eq, Show, Generic)+  deriving anyclass (NFData)++data CDecl l = CDecl !l !Level !Ident !(CExp l)+  deriving stock (Eq, Show, Generic)+  deriving anyclass (NFData)++-- Parses a concrete declaration from a string+cdeclParser :: Parser (CDecl SourceSpan)+cdeclParser = result where+  result = branch+    [ parser "declare" LevelType+    , parser "define" LevelTerm+    ]++  parser name lvl = around2 (flip CDecl lvl) (parens (symbol name *> ((,) <$> nonKeywordParser <*> cexpParser)))++runCDeclParser :: String -> IO (CExp SourceSpan)+runCDeclParser = runParserIO cexpParser++-- Just the expressions of our language that have nothing to do with naming+data Exp a =+    ExpBool !Bool+  | ExpInt !Int+  | ExpApp a a+  | ExpAdd a a+  | ExpIf a a a+  | ExpIsZero a+  | ExpAsc a a+  | ExpTyBool+  | ExpTyInt+  | ExpTyFun a a+  deriving stock (Eq, Show, Functor, Foldable, Traversable, Generic)+  deriving anyclass (NFData)++data Decl a = Decl !Level !Ident a+  deriving stock (Eq, Show, Functor, Foldable, Traversable, Generic)+  deriving anyclass (NFData)++-- An ExpScope without locations+type ExpScope a = Scope (NameOnly Ident) Exp a++type DeclScope a = Decl (ExpScope a)++-- A nameless equivalent to 'CExp'+type ExpLocScope l a = LocScope l (NameOnly Ident) Exp a++type DeclLocScope l a = Located l (Decl (ExpLocScope l a))++declLocScopeForget :: DeclLocScope l a -> DeclScope a+declLocScopeForget = fmap locScopeForget . locatedVal++declScopeAnno :: l -> DeclScope a -> DeclLocScope l a+declScopeAnno l = Located l . fmap (scopeAnno l)++-- Convert to nameless representation+expToNameless :: CExp l -> ExpLocScope l Ident+expToNameless ce =+  case ce of+    CExpBool l b -> LocScopeEmbed l (ExpBool b)+    CExpInt l i -> LocScopeEmbed l (ExpInt i)+    CExpApp l a b -> LocScopeEmbed l (ExpApp (expToNameless a) (expToNameless b))+    CExpAdd l a b -> LocScopeEmbed l (ExpAdd (expToNameless a) (expToNameless b))+    CExpIf l a b c -> LocScopeEmbed l (ExpIf (expToNameless a) (expToNameless b) (expToNameless c))+    CExpIsZero l a -> LocScopeEmbed l (ExpIsZero (expToNameless a))+    CExpVar l x -> LocScopeFree l x+    CExpAbs l x a -> runColocated (locScopeAbstract1 (NameOnly x) x (expToNameless a)) l+    CExpAsc l a b -> LocScopeEmbed l (ExpAsc (expToNameless a) (expToNameless b))+    CExpTyInt l -> LocScopeEmbed l ExpTyInt+    CExpTyBool l -> LocScopeEmbed l ExpTyBool+    CExpTyFun l a b -> LocScopeEmbed l (ExpTyFun (expToNameless a) (expToNameless b))++-- Convert back to named representation. Usually this isn't a necessary operation,+-- but we want to do round-trip testing+expToNamed :: ExpLocScope l Ident -> Maybe (CExp l)+expToNamed e =+  case e of+    LocScopeBound _ _ -> Nothing+    LocScopeFree l a -> pure (CExpVar l a)+    LocScopeBinder l _ (NameOnly x) b -> CExpAbs l x <$> expToNamed (locScopeUnAbstract1 x b)+    LocScopeEmbed l fe ->+      case fe of+        ExpBool b -> pure (CExpBool l b)+        ExpInt i -> pure (CExpInt l i)+        ExpApp a b -> CExpApp l <$> expToNamed a <*> expToNamed b+        ExpAdd a b -> CExpAdd l <$> expToNamed a <*> expToNamed b+        ExpIf a b c -> CExpIf l <$> expToNamed a <*> expToNamed b <*> expToNamed c+        ExpIsZero a -> CExpIsZero l <$> expToNamed a+        ExpAsc a b -> CExpAsc l <$> expToNamed a <*> expToNamed b+        ExpTyInt -> pure (CExpTyInt l)+        ExpTyBool -> pure (CExpTyBool l)+        ExpTyFun a b -> CExpTyFun l <$> expToNamed a <*> expToNamed b++declToNameless :: CDecl l -> DeclLocScope l Ident+declToNameless (CDecl l lvl i e) = Located l (Decl lvl i (expToNameless e))++declToNamed :: DeclLocScope l Ident -> Maybe (CDecl l)+declToNamed (Located l (Decl lvl i e)) = fmap (CDecl l lvl i) (expToNamed e)
+ test/Test/Blanks/ExpTest.hs view
@@ -0,0 +1,51 @@+module Test.Blanks.ExpTest where++import Blanks (pattern NameOnly, pattern ScopeBinder, pattern ScopeBound, pattern ScopeEmbed, pattern ScopeFree,+               locScopeForget, locScopeLocation)+import Control.DeepSeq (force)+import Test.Blanks.Exp (Exp (..), ExpScope, Ident (..), cexpLoc, expToNamed, expToNameless, runCExpParser)+import Test.Tasty (TestName, TestTree, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))++testSingle :: TestName -> String -> ExpScope Ident -> TestTree+testSingle name input expected = testCase name $ do+  namedExp <- runCExpParser input+  -- Force here just to test that we can+  let namelessExp = force (expToNameless namedExp)+  cexpLoc namedExp @?= locScopeLocation namelessExp+  let actual = locScopeForget namelessExp+  expected @?= actual+  let renamedExp = expToNamed namelessExp+  Just namedExp @?= renamedExp++testExp :: TestTree+testExp = testGroup "Exp" cases where+  xIdent = Ident "x"+  yIdent = Ident "y"+  xExp = ScopeFree xIdent+  yExp = ScopeFree yIdent+  trueExp = ScopeEmbed (ExpBool True)+  intExp = ScopeEmbed (ExpInt 42)+  negIntExp = ScopeEmbed (ExpInt (-42))+  boolTyExp = ScopeEmbed ExpTyBool+  intTyExp = ScopeEmbed ExpTyInt+  cases =+    [ testSingle "var" "x" xExp+    , testSingle "true" "#t" trueExp+    , testSingle "false" "#f" (ScopeEmbed (ExpBool False))+    , testSingle "int" "42" intExp+    , testSingle "neg int" "-42" negIntExp+    , testSingle "add" "(+ 42 -42)" (ScopeEmbed (ExpAdd intExp negIntExp))+    , testSingle "if" "(if #t 42 -42)" (ScopeEmbed (ExpIf trueExp intExp negIntExp))+    , testSingle "add var" "(+ 42 x)" (ScopeEmbed (ExpAdd intExp xExp))+    , testSingle "iszero" "(zero? 42)" (ScopeEmbed (ExpIsZero intExp))+    , testSingle "app" "(x y)" (ScopeEmbed (ExpApp xExp yExp))+    , testSingle "abs yy" "(lambda (y) y)" (ScopeBinder 1 (NameOnly yIdent) (ScopeBound 0))+    , testSingle "abs xyy" "(lambda (x) (lambda (y) y))" (ScopeBinder 1 (NameOnly xIdent) (ScopeBinder 1 (NameOnly yIdent) (ScopeBound 0)))+    , testSingle "abs xyx" "(lambda (x) (lambda (y) x))" (ScopeBinder 1 (NameOnly xIdent) (ScopeBinder 1 (NameOnly yIdent) (ScopeBound 1)))+    , testSingle "app abs" "((lambda (x) x) 42)" (ScopeEmbed (ExpApp (ScopeBinder 1 (NameOnly xIdent) (ScopeBound 0)) intExp))+    , testSingle "ty bool" "bool" boolTyExp+    , testSingle "ty int" "int" intTyExp+    , testSingle "ty fun" "(-> int bool)" (ScopeEmbed (ExpTyFun intTyExp boolTyExp))+    , testSingle "asc" "(: 42 int)" (ScopeEmbed (ExpAsc intExp intTyExp))+    ]
− test/Test/Blanks/LocScopeTest.hs
@@ -1,164 +0,0 @@-{-# LANGUAGE DeriveAnyClass #-}--module Test.Blanks.LocScopeTest where--import Blanks-import Control.DeepSeq (NFData, force)-import GHC.Generics (Generic)-import Test.Blanks.Parsing-import Test.Tasty-import Test.Tasty.HUnit---- A newtype indicating an identifier in our language-newtype Ident = Ident { unIdent :: String } deriving newtype (Eq, Show, Ord, NFData)---- The type of concrete expressions, labeled with source location-data CExp l =-    CExpTrue !l-  | CExpFalse !l-  | CExpInt !l !Int-  | CExpApp !l (CExp l) (CExp l)-  | CExpAdd !l (CExp l) (CExp l)-  | CExpIf !l (CExp l) (CExp l) (CExp l)-  | CExpIsZero !l (CExp l)-  | CExpVar !l !Ident-  | CExpAbs !l !Ident (CExp l)-  deriving (Eq, Show)---- Extracts the location from a concrete expression-cexpLoc :: CExp l -> l-cexpLoc ce =-  case ce of-    CExpTrue l -> l-    CExpFalse l -> l-    CExpInt l _ -> l-    CExpApp l _ _ -> l-    CExpAdd l _ _ -> l-    CExpIf l _ _ _ -> l-    CExpIsZero l _ -> l-    CExpVar l _ -> l-    CExpAbs l _ _ -> l---- Just the expressions of our language that have nothing to do with naming-data Exp a =-    ExpTrue-  | ExpFalse-  | ExpInt !Int-  | ExpApp a a-  | ExpAdd a a-  | ExpIf a a a-  | ExpIsZero a-  deriving stock (Eq, Show, Functor, Foldable, Traversable, Generic)-  deriving anyclass (NFData)---- A nameless equivalent to 'CExp'-type ExpScope l = LocScope l (NameOnly Ident) Exp Ident---- Parsers a concrete expression from a string-cexpParser :: Parser (CExp SourceSpan)-cexpParser = result where-  result = branch-    [ trueParser-    , falseParser-    , intParser-    , addParser-    , ifParser-    , isZeroParser-    , absParser-    , appParser-    , varParser-    ]--  trueParser = around (const . CExpTrue) (symbol "#t")--  falseParser = around (const . CExpFalse) (symbol "#f")--  intParser = around CExpInt signed--  addParser = around2 CExpAdd (parens (symbol "+" >> double cexpParser))--  ifParser = around3 CExpIf (parens (symbol "if" >> triple cexpParser))--  isZeroParser = around CExpIsZero (parens (symbol "zero?" >> cexpParser))--  absParser = around2 CExpAbs $ parens $ do-    _ <- symbol "lambda"-    n <- parens (fmap Ident identifier)-    b <- cexpParser-    pure (n, b)--  appParser = around2 CExpApp (parens (double cexpParser))--  varParser = around CExpVar (fmap Ident identifier)---- Convert to nameless representation-nameless :: CExp l -> ExpScope l-nameless ce =-  case ce of-    CExpTrue l -> LocScopeEmbed l ExpTrue-    CExpFalse l -> LocScopeEmbed l ExpFalse-    CExpInt l i -> LocScopeEmbed l (ExpInt i)-    CExpApp l a b -> LocScopeEmbed l (ExpApp (nameless a) (nameless b))-    CExpAdd l a b -> LocScopeEmbed l (ExpAdd (nameless a) (nameless b))-    CExpIf l a b c -> LocScopeEmbed l (ExpIf (nameless a) (nameless b) (nameless c))-    CExpIsZero l a -> LocScopeEmbed l (ExpIsZero (nameless a))-    CExpVar l x -> LocScopeFree l x-    CExpAbs l x a -> runColocated (blankAbstract1 (NameOnly x) x (nameless a)) l---- Convert back to named representation. Usually this isn't a necessary operation,--- but we want to do round-trip testing-named :: ExpScope l -> Maybe (CExp l)-named e =-  case e of-    LocScopeBound _ _ -> Nothing-    LocScopeFree l a -> pure (CExpVar l a)-    LocScopeBinder l _ (NameOnly x) b -> CExpAbs l x <$> named (blankUnAbstract1 x b)-    LocScopeEmbed l fe ->-      case fe of-        ExpTrue -> pure (CExpTrue l)-        ExpFalse -> pure (CExpFalse l)-        ExpInt i -> pure (CExpInt l i)-        ExpApp a b -> CExpApp l <$> named a <*> named b-        ExpAdd a b -> CExpAdd l <$> named a <*> named b-        ExpIf a b c -> CExpIf l <$> named a <*> named b <*> named c-        ExpIsZero a -> CExpIsZero l <$> named a---- An ExpScope without locations-type ExpSimpleScope = Scope (NameOnly Ident) Exp Ident--testSingle :: TestName -> String -> ExpSimpleScope -> TestTree-testSingle name input expected = testCase name $ do-  namedExp <- runParserIO cexpParser input-  -- Force here just to test that we can-  let namelessExp = force (nameless namedExp)-  cexpLoc namedExp @?= locScopeLocation namelessExp-  let actual = locScopeForget namelessExp-  expected @?= actual-  let renamedExp = named namelessExp-  Just namedExp @?= renamedExp--testLocScope :: TestTree-testLocScope = testGroup "LocScope" cases where-  xIdent = Ident "x"-  yIdent = Ident "y"-  xExp = ScopeFree xIdent-  yExp = ScopeFree yIdent-  trueExp = ScopeEmbed ExpTrue-  intExp = ScopeEmbed (ExpInt 42)-  negIntExp = ScopeEmbed (ExpInt (-42))-  cases =-    [ testSingle "var" "x" xExp-    , testSingle "true" "#t" trueExp-    , testSingle "false" "#f" (ScopeEmbed ExpFalse)-    , testSingle "int" "42" intExp-    , testSingle "neg int" "-42" negIntExp-    , testSingle "add" "(+ 42 -42)" (ScopeEmbed (ExpAdd intExp negIntExp))-    , testSingle "if" "(if #t 42 -42)" (ScopeEmbed (ExpIf trueExp intExp negIntExp))-    , testSingle "add var" "(+ 42 x)" (ScopeEmbed (ExpAdd intExp xExp))-    , testSingle "iszero" "(zero? 42)" (ScopeEmbed (ExpIsZero intExp))-    , testSingle "app" "(x y)" (ScopeEmbed (ExpApp xExp yExp))-    , testSingle "abs yy" "(lambda (y) y)" (ScopeBinder 1 (NameOnly yIdent) (ScopeBound 0))-    , testSingle "abs xyy" "(lambda (x) (lambda (y) y))" (ScopeBinder 1 (NameOnly xIdent) (ScopeBinder 1 (NameOnly yIdent) (ScopeBound 0)))-    , testSingle "abs xyx" "(lambda (x) (lambda (y) x))" (ScopeBinder 1 (NameOnly xIdent) (ScopeBinder 1 (NameOnly yIdent) (ScopeBound 1)))-    , testSingle "app abs" "((lambda (x) x) 42)" (ScopeEmbed (ExpApp (ScopeBinder 1 (NameOnly xIdent) (ScopeBound 0)) intExp))-    ]
test/Test/Blanks/Parsing.hs view
@@ -22,11 +22,11 @@     Right a -> pure a  data SourceSpan = SourceSpan-  { _ssName :: !FilePath-  , _ssStartLine :: !MP.Pos-  , _ssStartColumn :: !MP.Pos-  , _ssEndLine :: !MP.Pos-  , _ssEndColumn :: !MP.Pos+  { ssName :: !FilePath+  , ssStartLine :: !MP.Pos+  , ssStartColumn :: !MP.Pos+  , ssEndLine :: !MP.Pos+  , ssEndColumn :: !MP.Pos   } deriving stock (Eq, Show, Ord, Generic)     deriving anyclass (NFData) 
test/Test/Blanks/ScopeTest.hs view
@@ -2,42 +2,17 @@   ( testScope   ) where -import Blanks-import Control.Monad.Identity (Identity (..))-import Data.Set (Set)+import Blanks (SubError (..), scopeApply1, scopeInstantiate1) import qualified Data.Set as Set import Test.Blanks.Assertions ((@/=))-import Test.Tasty-import Test.Tasty.HUnit--type BareScope = Scope (NameOnly Char) Identity Char--abst :: Char -> BareScope -> BareScope-abst a = runIdentity . blankAbstract1 (Name a ()) a--bound :: Int -> BareScope-bound = ScopeBound--var :: Char -> BareScope-var = pure--freeVars :: BareScope -> Set Char-freeVars = foldMap Set.singleton+import Test.Blanks.SimpleScope (abst, embed, freeVars, sbound, sconst, sflip, sfree, sfree2, sid, spair, svar, svar2,+                                swonky, swonky2, var)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))  testScope :: TestTree testScope =-  let svar = var 'x'-      sbound = bound 0-      sfree = abst 'y' (var 'x')-      sfree2 = abst 'z' (abst 'y' (var 'x'))-      sid = abst 'x' (var 'x')-      swonky = abst 'x' (bound 0)-      sconst = abst 'x' (abst 'y' (var 'x'))-      sflip = abst 'x' (abst 'y' (var 'y'))-      svar2 = var 'e'-      swonky2 = abst 'x' svar2--      testEq =+  let testEq =         testCase "eq" $ do           svar @?= svar           svar @/= svar2@@ -57,33 +32,38 @@           freeVars swonky @?= Set.empty           freeVars sconst @?= Set.empty           freeVars sflip @?= Set.empty-          freeVars svar2 @=? Set.singleton 'e'+          freeVars svar2 @?= Set.singleton 'e'           freeVars swonky2 @?= Set.singleton 'e'+          freeVars spair @?= Set.singleton 'x'        testInstantiate =         testCase "instantiate" $ do-          blankInstantiate1 (pure svar2) svar @?= svar-          blankInstantiate1 (pure svar2) sbound @?= svar2-          blankInstantiate1 (pure svar2) sid @?= sid-          blankInstantiate1 (pure svar2) swonky @?= swonky2+          scopeInstantiate1 svar2 svar @?= svar+          scopeInstantiate1 svar2 sbound @?= svar2+          scopeInstantiate1 svar2 sid @?= sid+          scopeInstantiate1 svar2 swonky @?= swonky2+          scopeInstantiate1 svar2 spair @?= embed svar svar2        testApply =         testCase "apply" $ do-          blankApply1 (pure svar2) sid @?= Right svar2-          blankApply1 (pure svar2) swonky @?= Right sbound-          blankApply1 (pure svar2) sconst @?= Right swonky2-          blankApply1 (pure svar2) sflip @?= Right sid+          scopeApply1 svar2 sid @?= Right svar2+          scopeApply1 svar2 swonky @?= Right sbound+          scopeApply1 svar2 sconst @?= Right swonky2+          scopeApply1 svar2 sflip @?= Right sid+          scopeApply1 svar2 svar @?= Left NonBinderError        testVarSub =         testCase "var sub" $ do           (svar >>= const svar2) @?= svar2           (sfree >>= const svar2) @?= abst 'y' svar2           (sfree2 >>= const svar2) @?= abst 'c' (abst 'd' svar2)+          (spair >>= const svar2) @?= embed svar2 sbound        testIdSub =         testCase "id sub" $ do           (svar >>= const sid) @?= sid           (sfree >>= const sid) @?= abst 'y' sid           (sfree2 >>= const sid) @?= abst 'c' (abst 'd' sid)+          (spair >>= const sid) @?= embed sid sbound     in testGroup "Scope" [testEq, testFreeVars, testInstantiate, testApply, testVarSub, testIdSub]
+ test/Test/Blanks/SimpleScope.hs view
@@ -0,0 +1,43 @@+module Test.Blanks.SimpleScope where++import Blanks (NameOnly, pattern NameOnly, Scope, pattern ScopeBound, pattern ScopeEmbed, Tracked, locScopeLocation,+               scopeAbstract1, trackScopeSimple)+import Data.Set (Set)+import qualified Data.Set as Set++data SimpleFunctor a = SimpleFunctor !a !a+  deriving stock (Eq, Show, Functor, Foldable, Traversable)++type SimpleScope = Scope (NameOnly Char) SimpleFunctor Char++abst :: Char -> SimpleScope -> SimpleScope+abst a = scopeAbstract1 (NameOnly a) a++bound :: Int -> SimpleScope+bound = ScopeBound++var :: Char -> SimpleScope+var = pure++freeVars :: SimpleScope -> Set Char+freeVars = foldMap Set.singleton++tracked :: SimpleScope -> Tracked Char+tracked = locScopeLocation . trackScopeSimple++embed :: SimpleScope -> SimpleScope -> SimpleScope+embed x y = ScopeEmbed (SimpleFunctor x y)++svar, sbound, sfree, sfree2, sid, swonky, sconst, sflip, svar2, swonky2, spair, swonky3 :: SimpleScope+svar = var 'x'+sbound = bound 0+sfree = abst 'y' (var 'x')+sfree2 = abst 'z' (abst 'y' (var 'x'))+sid = abst 'x' (var 'x')+swonky = abst 'x' (bound 0)+sconst = abst 'x' (abst 'y' (var 'x'))+sflip = abst 'x' (abst 'y' (var 'y'))+svar2 = var 'e'+swonky2 = abst 'x' svar2+spair = embed svar sbound+swonky3 = abst 'x' (bound 3)
+ test/Test/Blanks/SplitScope.hs view
@@ -0,0 +1,45 @@+module Test.Blanks.SplitScope where++import Blanks (BinderId, BinderScope, LocScope, pattern LocScopeBound, pattern LocScopeEmbed, NameOnly,+               pattern NameOnly, SplitBinder (..), SplitFunctor (..), SplitResult, Tracked,+               WithTracked (withTrackedState), locScopeAbstract1, locScopeInnerBinder1, locScopeLocation, runColocated,+               scopeAnno, splitLocScope, trackScope)+import qualified Data.Sequence as Seq+import Data.Set (Set)+import qualified Data.Set as Set+import Test.Blanks.SimpleScope (SimpleFunctor (..), SimpleScope)++type SplitScope = LocScope () (NameOnly Char) (SplitFunctor SimpleFunctor) Char+type SplitInnerBinder = BinderScope (NameOnly Char) SplitScope+type SplitOuterBinder = SplitBinder () (NameOnly Char) SimpleFunctor Char+type SplitScopeResult = SplitResult () (NameOnly Char) SimpleFunctor Char++abstSplit :: Char -> SplitScope -> SplitScope+abstSplit a = flip runColocated () . locScopeAbstract1 (NameOnly a) a++innerBinderSplit :: Char -> SplitScope -> SplitInnerBinder+innerBinderSplit a = locScopeInnerBinder1 (NameOnly a) a++boundSplit :: Int -> SplitScope+boundSplit = LocScopeBound ()++varSplit :: Char -> SplitScope+varSplit = pure++freeVarsSplit :: SplitScope -> Set Char+freeVarsSplit = foldMap Set.singleton++trackedSplit :: SplitScope -> Tracked Char+trackedSplit = withTrackedState . locScopeLocation . trackScope++embedSplit :: SplitScope -> SplitScope -> SplitScope+embedSplit x y = LocScopeEmbed () (SplitFunctorBase (SimpleFunctor x y))++closureSplit :: BinderId -> [Int] -> SplitScope+closureSplit bid vars = LocScopeEmbed () (SplitFunctorClosure bid (Seq.fromList vars))++outerBinderSplit :: Int -> [Char] -> SplitInnerBinder -> SplitOuterBinder+outerBinderSplit a = SplitBinder a . Set.fromList++simpleSplit :: SimpleScope -> SplitScopeResult+simpleSplit s = splitLocScope (trackScope (scopeAnno () s))
+ test/Test/Blanks/SplitTest.hs view
@@ -0,0 +1,70 @@+module Test.Blanks.SplitTest+  ( testSplit+  ) where++import Blanks (BinderId, SplitResult (..), Tracked, mkTrackedBound, mkTrackedFree)+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map+import Test.Blanks.SimpleScope (SimpleScope, sbound, sconst, sflip, sfree, sfree2, sid, spair, svar, swonky, swonky3)+import Test.Blanks.SplitScope (SplitOuterBinder, SplitScope, boundSplit, closureSplit, embedSplit, innerBinderSplit,+                               outerBinderSplit, simpleSplit, varSplit)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))++data SplitCase = SplitCase+  { splitCaseName :: !String+  , splitCaseScopeIn :: !SimpleScope+  , splitCaseTrackedOut :: !(Tracked Char)+  , splitCaseScopeOut :: !SplitScope+  , splitCaseBinders :: !(Map BinderId SplitOuterBinder)+  } deriving stock (Eq, Show)++splitCases :: [SplitCase]+splitCases =+  let xvar = varSplit 'x'+      xbound = boundSplit 0+      xpair = embedSplit xvar xbound+  in [ SplitCase "var" svar (mkTrackedFree 'x') xvar Map.empty+    , SplitCase "bound" sbound (mkTrackedBound 0) xbound Map.empty+    , SplitCase "pair" spair (mkTrackedFree 'x' <> mkTrackedBound 0) xpair Map.empty+    , let ib = innerBinderSplit 'y' (varSplit 'x')+          ob = outerBinderSplit 0 ['x'] ib+      in SplitCase "free" sfree mempty (closureSplit 0 []) (Map.singleton 0 ob)+    , let ibY = innerBinderSplit 'y' (varSplit 'x')+          obY = outerBinderSplit 0 ['x'] ibY+          ibZ = innerBinderSplit 'z' (closureSplit 1 [])+          obZ = outerBinderSplit 0 ['x'] ibZ+      in SplitCase "free2" sfree2 mempty (closureSplit 0 []) (Map.fromList [(0, obZ), (1, obY)])+    , let ib = innerBinderSplit 'x' (varSplit 'x')+          ob = outerBinderSplit 0 [] ib+      in SplitCase "id" sid mempty (closureSplit 0 []) (Map.singleton 0 ob)+    , let ib = innerBinderSplit 'x' (boundSplit 0)+          ob = outerBinderSplit 1 [] ib+      in SplitCase "wonky" swonky (mkTrackedBound 0) (closureSplit 0 [0]) (Map.singleton 0 ob)+    , let ibY = innerBinderSplit 'y' (boundSplit 0)+          obY = outerBinderSplit 1 [] ibY+          ibZ = innerBinderSplit 'x' (closureSplit 1 [0])+          obZ = outerBinderSplit 0 [] ibZ+      in SplitCase "const" sconst mempty (closureSplit 0 []) (Map.fromList [(0, obZ), (1, obY)])+    , let ibY = innerBinderSplit 'y' (varSplit 'y')+          obY = outerBinderSplit 0 [] ibY+          ibZ = innerBinderSplit 'x' (closureSplit 1 [])+          obZ = outerBinderSplit 0 [] ibZ+      in SplitCase "flip" sflip mempty (closureSplit 0 []) (Map.fromList [(0, obZ), (1, obY)])+    , let ib = innerBinderSplit 'x' (boundSplit 3)+          ob = outerBinderSplit 1 [] ib+      in SplitCase "wonky3" swonky3 (mkTrackedBound 3) (closureSplit 0 [3]) (Map.singleton 0 ob)+    ]++runSplitCase :: SplitCase -> IO ()+runSplitCase (SplitCase _ scopeIn trackedOut scopeOut binders) = do+  let SplitResult actualTrackedOut actualScopeOut actualBinders = simpleSplit scopeIn+  actualTrackedOut @?= trackedOut+  actualScopeOut @?= scopeOut+  actualBinders @?= binders++testSplitCase :: SplitCase -> TestTree+testSplitCase c = testCase (splitCaseName c) (runSplitCase c)++testSplit :: TestTree+testSplit = testGroup "Split" (fmap testSplitCase splitCases)
+ test/Test/Blanks/TrackedTest.hs view
@@ -0,0 +1,24 @@+module Test.Blanks.TrackedTest+  ( testTracked+  ) where++import Blanks (mkTrackedBound, mkTrackedFree)+import Test.Blanks.SimpleScope (sbound, sconst, sflip, sfree, sfree2, sid, spair, svar, svar2, swonky, swonky2, swonky3,+                                tracked)+import Test.Tasty (TestTree)+import Test.Tasty.HUnit (testCase, (@?=))++testTracked :: TestTree+testTracked = testCase "tracked" $ do+  tracked svar @?= mkTrackedFree 'x'+  tracked sbound @?= mkTrackedBound 0+  tracked sfree @?= mkTrackedFree 'x'+  tracked sfree2 @?= mkTrackedFree 'x'+  tracked sid @?= mempty+  tracked swonky @?= mkTrackedBound 0+  tracked sconst @?= mempty+  tracked sflip @?= mempty+  tracked svar2 @?= mkTrackedFree 'e'+  tracked swonky2 @?= mkTrackedFree 'e'+  tracked spair @?= mkTrackedFree 'x' <> mkTrackedBound 0+  tracked swonky3 @?= mkTrackedBound 3