free-foil 0.2.0 → 0.3.0
raw patch · 15 files changed
+1183/−323 lines, 15 filesdep ~arraydep ~bifunctorsdep ~containersPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: array, bifunctors, containers, deepseq, kind-generics, template-haskell, text
API changes (from Hackage documentation)
- Control.Monad.Free.Foil: class ZipMatch (sig :: Type -> Type -> Type)
- Control.Monad.Free.Foil: instance (Control.Monad.Free.Foil.ZipMatch f, Control.Monad.Free.Foil.ZipMatch g) => Control.Monad.Free.Foil.ZipMatch (Data.Bifunctor.Sum.Sum f g)
- Control.Monad.Free.Foil: instance (Data.Bifunctor.Bifunctor sig, Control.Monad.Foil.Internal.CoSinkable binder) => Control.Monad.Foil.Internal.Sinkable (Control.Monad.Free.Foil.AST binder sig)
- Control.Monad.Free.Foil: instance (Data.Bifunctor.Bifunctor sig, Control.Monad.Foil.Internal.CoSinkable binder) => Control.Monad.Foil.Relative.RelMonad Control.Monad.Foil.Internal.Name (Control.Monad.Free.Foil.AST binder sig)
- Control.Monad.Free.Foil: zipMatch :: ZipMatch sig => sig scope term -> sig scope' term' -> Maybe (sig (scope, scope') (term, term'))
- Control.Monad.Free.Foil.Generic: ($dmzipMatchWithK) :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (ZipMatchK f, GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs) => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
- Control.Monad.Free.Foil.Generic: [:^:] :: forall {k1} a b c (as1 :: LoT k1) (bs1 :: LoT k1) (cs1 :: LoT k1). (a -> b -> Maybe c) -> Mappings as1 bs1 cs1 -> Mappings (a ':&&: as1) (b ':&&: bs1) (c ':&&: cs1)
- Control.Monad.Free.Foil.Generic: [M0] :: Mappings 'LoT0 'LoT0 'LoT0
- Control.Monad.Free.Foil.Generic: applyMappings :: forall (as :: LoT d) (bs :: LoT d) (cs :: LoT d). ApplyMappings v => Mappings as bs cs -> Interpret ('Var v) as -> Interpret ('Var v) bs -> Maybe (Interpret ('Var v) cs)
- Control.Monad.Free.Foil.Generic: class ApplyMappings (v :: TyVar d Type)
- Control.Monad.Free.Foil.Generic: class GZipMatch (f :: LoT k -> Type) where {
- Control.Monad.Free.Foil.Generic: class PairMappings (as :: LoT k) (bs :: LoT k)
- Control.Monad.Free.Foil.Generic: class ZipMatchFields (t :: Atom d Type) where {
- Control.Monad.Free.Foil.Generic: class ZipMatchK (f :: k)
- Control.Monad.Free.Foil.Generic: data Mappings (as :: LoT k) (bs :: LoT k) (cs :: LoT k)
- Control.Monad.Free.Foil.Generic: genericZipMatch2 :: forall sig scope scope' term term'. (GenericK sig, GZipMatch (RepK sig), ReqsZipMatch (RepK sig) (scope ':&&: (term ':&&: 'LoT0)) (scope' ':&&: (term' ':&&: 'LoT0))) => sig scope term -> sig scope' term' -> Maybe (sig (scope, scope') (term, term'))
- Control.Monad.Free.Foil.Generic: genericZipMatchK :: forall {k} (f :: k) (as :: LoT k) (bs :: LoT k). (GenericK f, GZipMatch (RepK f), ReqsZipMatch (RepK f) as bs, PairMappings as bs) => (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: ZipLoT as bs)
- Control.Monad.Free.Foil.Generic: genericZipMatchWithK :: forall {k} (f :: k) (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs) => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
- Control.Monad.Free.Foil.Generic: gzipMatchWith :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (GZipMatch f, ReqsZipMatchWith f as bs cs) => Mappings as bs cs -> f as -> f bs -> Maybe (f cs)
- Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ApplyMappings 'Data.PolyKinded.Atom.VZ
- Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.GZipMatch GHC.Generics.U1
- Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.GZipMatch GHC.Generics.V1
- Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.PairMappings 'Data.PolyKinded.LoT0 'Data.PolyKinded.LoT0
- Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK Data.Either.Either
- Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK GHC.Maybe.Maybe
- Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK []
- Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK a => Control.Monad.Free.Foil.Generic.ZipMatchK (Data.Either.Either a)
- Control.Monad.Free.Foil.Generic: instance Control.Monad.Free.Foil.Generic.ZipMatchK k => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Kon k)
- Control.Monad.Free.Foil.Generic: instance forall d (a :: Data.PolyKinded.Atom.Atom d (Fcf.Core.Exp (*))). (TypeError ...) => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Eval a)
- Control.Monad.Free.Foil.Generic: instance forall d (c :: Data.PolyKinded.Atom.Atom d GHC.Types.Constraint) (a :: Data.PolyKinded.Atom.Atom d (*)). (TypeError ...) => Control.Monad.Free.Foil.Generic.ZipMatchFields (c 'Data.PolyKinded.Atom.:=>>: a)
- Control.Monad.Free.Foil.Generic: instance forall d (t :: Data.PolyKinded.Atom.Atom d (*)) (k :: * -> *). (Control.Monad.Free.Foil.Generic.ZipMatchFields t, Control.Monad.Free.Foil.Generic.ZipMatchK k) => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Kon k 'Data.PolyKinded.Atom.:@: t)
- Control.Monad.Free.Foil.Generic: instance forall d (t1 :: Data.PolyKinded.Atom.Atom d (*)) (t2 :: Data.PolyKinded.Atom.Atom d (*)) (k :: * -> * -> *). (Control.Monad.Free.Foil.Generic.ZipMatchFields t1, Control.Monad.Free.Foil.Generic.ZipMatchFields t2, Control.Monad.Free.Foil.Generic.ZipMatchK k) => Control.Monad.Free.Foil.Generic.ZipMatchFields (('Data.PolyKinded.Atom.Kon k 'Data.PolyKinded.Atom.:@: t1) 'Data.PolyKinded.Atom.:@: t2)
- Control.Monad.Free.Foil.Generic: instance forall d (v :: Data.PolyKinded.Atom.TyVar d (*)). Control.Monad.Free.Foil.Generic.ApplyMappings v => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Var v)
- Control.Monad.Free.Foil.Generic: instance forall d k1 (f :: Data.PolyKinded.Atom.Atom d (k1 -> *)) (t :: Data.PolyKinded.Atom.Atom d k1). (TypeError ...) => Control.Monad.Free.Foil.Generic.ZipMatchFields (f 'Data.PolyKinded.Atom.:@: t)
- Control.Monad.Free.Foil.Generic: instance forall d1 d (a :: Data.PolyKinded.Atom.Atom (d1 -> d) (*)). (TypeError ...) => Control.Monad.Free.Foil.Generic.ZipMatchFields ('Data.PolyKinded.Atom.ForAll a)
- Control.Monad.Free.Foil.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) (c :: Data.PolyKinded.Atom.Atom k GHC.Types.Constraint). Control.Monad.Free.Foil.Generic.GZipMatch f => Control.Monad.Free.Foil.Generic.GZipMatch (c Generics.Kind.:=>: f)
- Control.Monad.Free.Foil.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) (g :: Data.PolyKinded.LoT k -> *). (Control.Monad.Free.Foil.Generic.GZipMatch f, Control.Monad.Free.Foil.Generic.GZipMatch g) => Control.Monad.Free.Foil.Generic.GZipMatch (f GHC.Generics.:*: g)
- Control.Monad.Free.Foil.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) (g :: Data.PolyKinded.LoT k -> *). (Control.Monad.Free.Foil.Generic.GZipMatch f, Control.Monad.Free.Foil.Generic.GZipMatch g) => Control.Monad.Free.Foil.Generic.GZipMatch (f GHC.Generics.:+: g)
- Control.Monad.Free.Foil.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) i (c :: GHC.Generics.Meta). Control.Monad.Free.Foil.Generic.GZipMatch f => Control.Monad.Free.Foil.Generic.GZipMatch (GHC.Generics.M1 i c f)
- Control.Monad.Free.Foil.Generic: instance forall k (t :: Data.PolyKinded.Atom.Atom k (*)). Control.Monad.Free.Foil.Generic.ZipMatchFields t => Control.Monad.Free.Foil.Generic.GZipMatch (Generics.Kind.Field t)
- Control.Monad.Free.Foil.Generic: instance forall k1 k2 (f :: Data.PolyKinded.LoT (k2 -> k1) -> *). (TypeError ...) => Control.Monad.Free.Foil.Generic.GZipMatch (Generics.Kind.Exists k2 f)
- Control.Monad.Free.Foil.Generic: instance forall ks (as :: Data.PolyKinded.LoT ks) (bs :: Data.PolyKinded.LoT ks) a b. Control.Monad.Free.Foil.Generic.PairMappings as bs => Control.Monad.Free.Foil.Generic.PairMappings (a 'Data.PolyKinded.:&&: as) (b 'Data.PolyKinded.:&&: bs)
- Control.Monad.Free.Foil.Generic: instance forall tys (v :: Data.PolyKinded.Atom.TyVar tys (*)) ty. Control.Monad.Free.Foil.Generic.ApplyMappings v => Control.Monad.Free.Foil.Generic.ApplyMappings ('Data.PolyKinded.Atom.VS v)
- Control.Monad.Free.Foil.Generic: pairMappings :: PairMappings as bs => Mappings as bs (ZipLoT as bs)
- Control.Monad.Free.Foil.Generic: type ReqsZipMatch (f :: LoT k -> Type) (as :: LoT k) (bs :: LoT k) = ReqsZipMatchWith f as bs ZipLoT as bs
- Control.Monad.Free.Foil.Generic: type ReqsZipMatchFieldsWith (t :: Atom d Type) (as :: LoT d) (bs :: LoT d) (cs :: LoT d);
- Control.Monad.Free.Foil.Generic: type ReqsZipMatchWith (f :: LoT k -> Type) (as :: LoT k) (bs :: LoT k) (cs :: LoT k);
- Control.Monad.Free.Foil.Generic: type family ZipLoT (as :: LoT k) (bs :: LoT k) :: LoT k
- Control.Monad.Free.Foil.Generic: zipMatchFieldsWith :: forall (as :: LoT d) (bs :: LoT d) (cs :: LoT d). (ZipMatchFields t, ReqsZipMatchFieldsWith t as bs cs) => Mappings as bs cs -> Field t as -> Field t bs -> Maybe (Field t cs)
- Control.Monad.Free.Foil.Generic: zipMatchK :: forall {k} (f :: k) (as :: LoT k) (bs :: LoT k). (ZipMatchK f, PairMappings as bs) => (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: ZipLoT as bs)
- Control.Monad.Free.Foil.Generic: zipMatchViaChooseLeft :: forall {k} (as :: LoT k) (bs :: LoT k) (cs :: LoT k) a. Mappings as bs cs -> a -> a -> Maybe a
- Control.Monad.Free.Foil.Generic: zipMatchViaEq :: forall {k} a (as :: LoT k) (bs :: LoT k) (cs :: LoT k). Eq a => Mappings as bs cs -> a -> a -> Maybe a
- Control.Monad.Free.Foil.Generic: zipMatchWithK :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). ZipMatchK f => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
- Control.Monad.Free.Foil.Generic: }
- Control.Monad.Free.Foil.TH.ZipMatch: deriveZipMatch :: Name -> Q [Dec]
+ Control.Monad.Foil: ($dmcoSinkabilityProof) :: forall (n :: S) (n' :: S) (l :: S) r. (CoSinkable pattern, GenericK pattern, GSinkableK (RepK pattern)) => (Name n -> Name n') -> pattern n l -> (forall (l' :: S). () => (Name l -> Name l') -> pattern n' l' -> r) -> r
+ Control.Monad.Foil: ($dmsinkabilityProof) :: forall (n :: S) (l :: S). (Sinkable e, GenericK e, GSinkableK (RepK e)) => (Name n -> Name l) -> e n -> e l
+ Control.Monad.Foil: ($dmsinkabilityProofK) :: forall (as :: LoT (S -> k)) (bs :: LoT (S -> k)) r. (SinkableK f, GenericK f, GSinkableK (RepK f)) => RenamingsK as bs -> (f :@@: as) -> (forall (cs :: LoT (S -> k)). () => RenamingsK as cs -> (f :@@: cs) -> r) -> r
+ Control.Monad.Foil: ($dmunifyPatterns) :: forall (n :: S) (l :: S) (r :: S). (UnifiablePattern pattern, CoSinkable pattern, Distinct n) => pattern n l -> pattern n r -> UnifyNameBinders pattern n l r
+ Control.Monad.Foil: ($dmwithPattern) :: forall (o :: S) f (n :: S) (l :: S) r. (CoSinkable pattern, Distinct o, GenericK pattern, GValidNameBinders pattern (RepK pattern), GHasNameBinders (RepK pattern)) => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> pattern n l -> (forall (o' :: S). DExt o o' => f n l o o' -> pattern o o' -> r) -> r
+ Control.Monad.Foil: class HasNameBinders (f :: S -> S -> Type)
+ Control.Monad.Foil: class SinkableK (f :: S -> k)
+ Control.Monad.Foil: getNameBinders :: forall (n :: S) (l :: S). HasNameBinders f => f n l -> NameBinders n l
+ Control.Monad.Foil: sinkabilityProofK :: forall (as :: LoT (S -> k)) (bs :: LoT (S -> k)) r. SinkableK f => RenamingsK as bs -> (f :@@: as) -> (forall (cs :: LoT (S -> k)). () => RenamingsK as cs -> (f :@@: cs) -> r) -> r
+ Control.Monad.Foil.Internal: ($dmcoSinkabilityProof) :: forall (n :: S) (n' :: S) (l :: S) r. (CoSinkable pattern, GenericK pattern, GSinkableK (RepK pattern)) => (Name n -> Name n') -> pattern n l -> (forall (l' :: S). () => (Name l -> Name l') -> pattern n' l' -> r) -> r
+ Control.Monad.Foil.Internal: ($dmgetNameBindersRaw) :: forall (n :: S) (l :: S). (HasNameBinders f, GenericK f, GHasNameBinders (RepK f)) => f n l -> [RawName]
+ Control.Monad.Foil.Internal: ($dmreallyUnsafeSetNameBindersRaw) :: forall (n :: S) (l :: S) (l' :: S). (HasNameBinders f, GenericK f, GValidNameBinders f (RepK f), GHasNameBinders (RepK f)) => f n l -> [RawName] -> (f n l', [RawName])
+ Control.Monad.Foil.Internal: ($dmsinkabilityProof) :: forall (n :: S) (l :: S). (Sinkable e, GenericK e, GSinkableK (RepK e)) => (Name n -> Name l) -> e n -> e l
+ Control.Monad.Foil.Internal: ($dmsinkabilityProofK) :: forall (as :: LoT (S -> k)) (bs :: LoT (S -> k)) r. (SinkableK f, GenericK f, GSinkableK (RepK f)) => RenamingsK as bs -> (f :@@: as) -> (forall (cs :: LoT (S -> k)). () => RenamingsK as cs -> (f :@@: cs) -> r) -> r
+ Control.Monad.Foil.Internal: ($dmunifyPatterns) :: forall (n :: S) (l :: S) (r :: S). (UnifiablePattern pattern, CoSinkable pattern, Distinct n) => pattern n l -> pattern n r -> UnifyNameBinders pattern n l r
+ Control.Monad.Foil.Internal: ($dmwithPattern) :: forall (o :: S) f (n :: S) (l :: S) r. (CoSinkable pattern, Distinct o, GenericK pattern, GValidNameBinders pattern (RepK pattern), GHasNameBinders (RepK pattern)) => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> pattern n l -> (forall (o' :: S). DExt o o' => f n l o o' -> pattern o o' -> r) -> r
+ Control.Monad.Foil.Internal: [RCons] :: forall {k1} (a :: S) (b :: S) (as1 :: LoT k1) (bs1 :: LoT k1). (Name a -> Name b) -> RenamingsK as1 bs1 -> RenamingsK (a ':&&: as1) (b ':&&: bs1)
+ Control.Monad.Foil.Internal: [RNil] :: RenamingsK 'LoT0 'LoT0
+ Control.Monad.Foil.Internal: [RSkip] :: forall {k1} {k2} (as1 :: LoT k1) (bs1 :: LoT k1) (k3 :: k2). RenamingsK as1 bs1 -> RenamingsK (k3 ':&&: as1) (k3 ':&&: bs1)
+ Control.Monad.Foil.Internal: class ExtractRenamingK (i :: TyVar k S)
+ Control.Monad.Foil.Internal: class GHasNameBinders (f :: k -> Type)
+ Control.Monad.Foil.Internal: class GSinkableK (p :: LoT k -> Type)
+ Control.Monad.Foil.Internal: class HasNameBinders (f :: S -> S -> Type)
+ Control.Monad.Foil.Internal: class SinkableK (f :: S -> k)
+ Control.Monad.Foil.Internal: data RenamingsK (as :: LoT k) (bs :: LoT k)
+ Control.Monad.Foil.Internal: extractRenamingK :: forall (as :: LoT k) (bs :: LoT k). ExtractRenamingK i => RenamingsK as bs -> Name (Interpret ('Var i) as) -> Name (Interpret ('Var i) bs)
+ Control.Monad.Foil.Internal: extractTwoRenamingsK :: forall k (i :: TyVar k S) (j :: TyVar k S) (as :: LoT k) (bs :: LoT k). (ExtractRenamingK i, ExtractRenamingK j) => RenamingsK as bs -> RenamingsK (Interpret ('Var i) as ':&&: (Interpret ('Var j) as ':&&: 'LoT0)) (Interpret ('Var i) bs ':&&: (Interpret ('Var j) bs ':&&: 'LoT0))
+ Control.Monad.Foil.Internal: getNameBinders :: forall (n :: S) (l :: S). HasNameBinders f => f n l -> NameBinders n l
+ Control.Monad.Foil.Internal: getNameBindersRaw :: forall (n :: S) (l :: S). HasNameBinders f => f n l -> [RawName]
+ Control.Monad.Foil.Internal: ggetNameBinders :: forall f (n :: S) (l :: S). (GenericK f, GHasNameBinders (RepK f)) => f n l -> NameBinders n l
+ Control.Monad.Foil.Internal: ggetNameBindersRaw :: forall (as :: k). GHasNameBinders f => f as -> [RawName]
+ Control.Monad.Foil.Internal: greallyUnsafeSetNameBindersRaw :: forall (as :: k) (bs :: k). GHasNameBinders f => f as -> [RawName] -> (f bs, [RawName])
+ Control.Monad.Foil.Internal: gsinkK :: forall {k} f (xs :: LoT k) (as :: LoT k) (bs :: LoT k). GSinkableK f => RenamingsK xs as -> RenamingsK xs bs -> f as -> f bs
+ Control.Monad.Foil.Internal: gsinkabilityProof1 :: forall f (n :: S) (n' :: S). GSinkableK f => (Name n -> Name n') -> f (n ':&&: 'LoT0) -> f (n' ':&&: 'LoT0)
+ Control.Monad.Foil.Internal: gsinkabilityProof2 :: forall f (n :: S) (n' :: S) (l :: S) r. GSinkableK f => (Name n -> Name n') -> f (n ':&&: (l ':&&: 'LoT0)) -> (forall (l' :: S). () => (Name l -> Name l') -> f (n' ':&&: (l' ':&&: 'LoT0)) -> r) -> r
+ Control.Monad.Foil.Internal: gsinkabilityProofK :: forall (as :: LoT k) (bs :: LoT k) r. GSinkableK p => RenamingsK as bs -> p as -> (forall (cs :: LoT k). () => RenamingsK as cs -> p cs -> r) -> r
+ Control.Monad.Foil.Internal: gsinkabilityProofK' :: forall {k} f (as :: LoT k) (bs :: LoT k). GSinkableK f => RenamingsK as bs -> f as -> f bs
+ Control.Monad.Foil.Internal: gunsafeSetNameBinders :: forall f (n :: S) (l :: S) (l' :: S). (GenericK f, GValidNameBinders f (RepK f), GHasNameBinders (RepK f)) => f n l -> NameBinders n l' -> f n l'
+ Control.Monad.Foil.Internal: gunsafeWithPatternViaHasNameBinders :: forall pattern f (o :: S) (n :: S) (l :: S) r. (Distinct o, GenericK pattern, GValidNameBinders pattern (RepK pattern), GHasNameBinders (RepK pattern)) => (forall (x :: S) (y :: S) (z :: S) r'. Distinct z => Scope z -> NameBinder x y -> (forall (z' :: S). DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r') -> (forall (x :: S) (z :: S) (z' :: S). DExt z z' => f x x z z') -> (forall (x :: S) (y :: S) (y' :: S) (z :: S) (z' :: S) (z'' :: S). (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'') -> Scope o -> pattern n l -> (forall (o' :: S). DExt o o' => f n l o o' -> pattern o o' -> r) -> r
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.ExtractRenamingK 'Data.PolyKinded.Atom.VZ
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.GHasNameBinders (Generics.Kind.Field ('Data.PolyKinded.Atom.Kon a))
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.GHasNameBinders GHC.Generics.U1
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.GHasNameBinders GHC.Generics.V1
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field ('Data.PolyKinded.Atom.Kon a))
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.GSinkableK GHC.Generics.U1
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.GSinkableK GHC.Generics.V1
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.HasNameBinders Control.Monad.Foil.Internal.NameBinder
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.HasNameBinders Control.Monad.Foil.Internal.NameBinderList
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.SinkableK Control.Monad.Foil.Internal.Name
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.SinkableK Control.Monad.Foil.Internal.NameBinder
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.SinkableK Control.Monad.Foil.Internal.NameBinderList
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.SinkableK Control.Monad.Foil.Internal.NameBinders
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.SinkableK Control.Monad.Foil.Internal.U2
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.SinkableK Control.Monad.Foil.Internal.V2
+ Control.Monad.Foil.Internal: instance Control.Monad.Foil.Internal.UnifiablePattern Control.Monad.Foil.Internal.NameBinderList
+ Control.Monad.Foil.Internal: instance Data.Foldable.Foldable (Control.Monad.Foil.Internal.NameMap n)
+ Control.Monad.Foil.Internal: instance Data.Traversable.Traversable (Control.Monad.Foil.Internal.NameMap n)
+ Control.Monad.Foil.Internal: instance GHC.Base.Functor (Control.Monad.Foil.Internal.NameMap n)
+ Control.Monad.Foil.Internal: instance Generics.Kind.GenericK Control.Monad.Foil.Internal.NameBinderList
+ Control.Monad.Foil.Internal: instance Generics.Kind.GenericK Control.Monad.Foil.Internal.U2
+ Control.Monad.Foil.Internal: instance Generics.Kind.GenericK Control.Monad.Foil.Internal.V2
+ Control.Monad.Foil.Internal: instance forall (f :: Control.Monad.Foil.Internal.S -> Control.Monad.Foil.Internal.S -> *) k (i :: Data.PolyKinded.Atom.TyVar k Control.Monad.Foil.Internal.S) (j :: Data.PolyKinded.Atom.TyVar k Control.Monad.Foil.Internal.S). (Control.Monad.Foil.Internal.SinkableK f, Control.Monad.Foil.Internal.ExtractRenamingK i, Control.Monad.Foil.Internal.ExtractRenamingK j) => Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field (('Data.PolyKinded.Atom.Kon f 'Data.PolyKinded.Atom.:@: 'Data.PolyKinded.Atom.Var i) 'Data.PolyKinded.Atom.:@: 'Data.PolyKinded.Atom.Var j))
+ Control.Monad.Foil.Internal: instance forall d (f :: Control.Monad.Foil.Internal.S -> Control.Monad.Foil.Internal.S -> *) (i :: Data.PolyKinded.Atom.TyVar d Control.Monad.Foil.Internal.S) (j :: Data.PolyKinded.Atom.TyVar d Control.Monad.Foil.Internal.S). Control.Monad.Foil.Internal.HasNameBinders f => Control.Monad.Foil.Internal.GHasNameBinders (Generics.Kind.Field (('Data.PolyKinded.Atom.Kon f 'Data.PolyKinded.Atom.:@: 'Data.PolyKinded.Atom.Var i) 'Data.PolyKinded.Atom.:@: 'Data.PolyKinded.Atom.Var j))
+ Control.Monad.Foil.Internal: instance forall d (x :: Data.PolyKinded.Atom.TyVar d (*)). Control.Monad.Foil.Internal.GHasNameBinders (Generics.Kind.Field ('Data.PolyKinded.Atom.Var x))
+ Control.Monad.Foil.Internal: instance forall d k (f :: Data.PolyKinded.LoT (k -> d) -> *). Control.Monad.Foil.Internal.GHasNameBinders f => Control.Monad.Foil.Internal.GHasNameBinders (Generics.Kind.Exists k f)
+ Control.Monad.Foil.Internal: instance forall d k1 k2 (f :: Data.PolyKinded.LoT d -> *) (i :: Data.PolyKinded.Atom.TyVar d k1) (j :: Data.PolyKinded.Atom.TyVar d k2). Control.Monad.Foil.Internal.GHasNameBinders f => Control.Monad.Foil.Internal.GHasNameBinders (('Data.PolyKinded.Atom.Var i Data.PolyKinded.Atom.:~~: 'Data.PolyKinded.Atom.Var j) Generics.Kind.:=>: f)
+ Control.Monad.Foil.Internal: instance forall k (a :: Data.PolyKinded.Atom.TyVar k (*)). Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field ('Data.PolyKinded.Atom.Var a))
+ Control.Monad.Foil.Internal: instance forall k (f :: * -> * -> *) (x :: Data.PolyKinded.Atom.Atom k (*)) (y :: Data.PolyKinded.Atom.Atom k (*)). (Data.Bifunctor.Bifunctor f, Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field x), Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field y)) => Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field (('Data.PolyKinded.Atom.Kon f 'Data.PolyKinded.Atom.:@: x) 'Data.PolyKinded.Atom.:@: y))
+ Control.Monad.Foil.Internal: instance forall k (f :: * -> *) (x :: Data.PolyKinded.Atom.Atom k (*)). (GHC.Base.Functor f, Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field x)) => Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field ('Data.PolyKinded.Atom.Kon f 'Data.PolyKinded.Atom.:@: x))
+ Control.Monad.Foil.Internal: instance forall k (f :: Control.Monad.Foil.Internal.S -> *) (i :: Data.PolyKinded.Atom.TyVar k Control.Monad.Foil.Internal.S). (Control.Monad.Foil.Internal.SinkableK f, Control.Monad.Foil.Internal.ExtractRenamingK i) => Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field ('Data.PolyKinded.Atom.Kon f 'Data.PolyKinded.Atom.:@: 'Data.PolyKinded.Atom.Var i))
+ Control.Monad.Foil.Internal: instance forall k (f :: Data.PolyKinded.LoT (Control.Monad.Foil.Internal.S -> k) -> *). Control.Monad.Foil.Internal.GSinkableK f => Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Exists Control.Monad.Foil.Internal.S f)
+ Control.Monad.Foil.Internal: instance forall k (f :: Data.PolyKinded.LoT k -> *) (g :: Data.PolyKinded.LoT k -> *). (Control.Monad.Foil.Internal.GSinkableK f, Control.Monad.Foil.Internal.GSinkableK g) => Control.Monad.Foil.Internal.GSinkableK (f GHC.Generics.:*: g)
+ Control.Monad.Foil.Internal: instance forall k (f :: Data.PolyKinded.LoT k -> *) (g :: Data.PolyKinded.LoT k -> *). (Control.Monad.Foil.Internal.GSinkableK f, Control.Monad.Foil.Internal.GSinkableK g) => Control.Monad.Foil.Internal.GSinkableK (f GHC.Generics.:+: g)
+ Control.Monad.Foil.Internal: instance forall k (f :: Data.PolyKinded.LoT k -> *) i (c :: GHC.Generics.Meta). Control.Monad.Foil.Internal.GSinkableK f => Control.Monad.Foil.Internal.GSinkableK (GHC.Generics.M1 i c f)
+ Control.Monad.Foil.Internal: instance forall k (f :: k -> *) (g :: k -> *). (Control.Monad.Foil.Internal.GHasNameBinders f, Control.Monad.Foil.Internal.GHasNameBinders g) => Control.Monad.Foil.Internal.GHasNameBinders (f GHC.Generics.:*: g)
+ Control.Monad.Foil.Internal: instance forall k (f :: k -> *) (g :: k -> *). (Control.Monad.Foil.Internal.GHasNameBinders f, Control.Monad.Foil.Internal.GHasNameBinders g) => Control.Monad.Foil.Internal.GHasNameBinders (f GHC.Generics.:+: g)
+ Control.Monad.Foil.Internal: instance forall k (f :: k -> *) i (c :: GHC.Generics.Meta). Control.Monad.Foil.Internal.GHasNameBinders f => Control.Monad.Foil.Internal.GHasNameBinders (GHC.Generics.M1 i c f)
+ Control.Monad.Foil.Internal: instance forall k k1 k2 (f :: Data.PolyKinded.LoT k -> *) (a :: Data.PolyKinded.Atom.Atom k k1) (b :: Data.PolyKinded.Atom.Atom k k2). Control.Monad.Foil.Internal.GSinkableK f => Control.Monad.Foil.Internal.GSinkableK ((a Data.PolyKinded.Atom.:~~: b) Generics.Kind.:=>: f)
+ Control.Monad.Foil.Internal: instance forall k1 d (f :: k1 -> *) (i :: Data.PolyKinded.Atom.TyVar d k1). Control.Monad.Foil.Internal.GHasNameBinders (Generics.Kind.Field ('Data.PolyKinded.Atom.Kon f 'Data.PolyKinded.Atom.:@: 'Data.PolyKinded.Atom.Var i))
+ Control.Monad.Foil.Internal: instance forall k1 k2 (f :: Data.PolyKinded.LoT (k2 -> k1) -> *). Control.Monad.Foil.Internal.GSinkableK f => Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Exists k2 f)
+ Control.Monad.Foil.Internal: instance forall k1 xs (f :: k1 -> Control.Monad.Foil.Internal.S -> *) (a :: k1). Control.Monad.Foil.Internal.SinkableK (f a) => Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field (('Data.PolyKinded.Atom.Kon f 'Data.PolyKinded.Atom.:@: 'Data.PolyKinded.Atom.Kon a) 'Data.PolyKinded.Atom.:@: Data.PolyKinded.Atom.Var0))
+ Control.Monad.Foil.Internal: instance forall k2 k3 xs (f :: k2 -> k3 -> Control.Monad.Foil.Internal.S -> *) (a :: k2) (b :: k3). Control.Monad.Foil.Internal.SinkableK (f a b) => Control.Monad.Foil.Internal.GSinkableK (Generics.Kind.Field ((('Data.PolyKinded.Atom.Kon f 'Data.PolyKinded.Atom.:@: 'Data.PolyKinded.Atom.Kon a) 'Data.PolyKinded.Atom.:@: 'Data.PolyKinded.Atom.Kon b) 'Data.PolyKinded.Atom.:@: Data.PolyKinded.Atom.Var0))
+ Control.Monad.Foil.Internal: instance forall xs x1 (x2 :: Data.PolyKinded.Atom.TyVar xs Control.Monad.Foil.Internal.S). Control.Monad.Foil.Internal.ExtractRenamingK x2 => Control.Monad.Foil.Internal.ExtractRenamingK ('Data.PolyKinded.Atom.VS x2)
+ Control.Monad.Foil.Internal: nameMapToScope :: forall (n :: S) a. NameMap n a -> Scope n
+ Control.Monad.Foil.Internal: putBackRenamingK :: forall (c :: S) (as :: LoT k) (bs :: LoT k). ExtractRenamingK i => (Name (Interpret ('Var i) as) -> Name c) -> RenamingsK as bs -> RenamingsK as (PutBackLoT i c bs)
+ Control.Monad.Foil.Internal: putBackTwoRenamingsK :: forall k (i :: TyVar k S) (j :: TyVar k S) (c1 :: S) (c2 :: S) (as :: LoT k) (bs :: LoT k). (ExtractRenamingK i, ExtractRenamingK j) => RenamingsK (Interpret ('Var i) as ':&&: (Interpret ('Var j) as ':&&: 'LoT0)) (c1 ':&&: (c2 ':&&: 'LoT0)) -> RenamingsK as bs -> RenamingsK as (PutBackLoT j c2 (PutBackLoT i c1 bs))
+ Control.Monad.Foil.Internal: reallyUnsafeSetNameBindersRaw :: forall (n :: S) (l :: S) (l' :: S). HasNameBinders f => f n l -> [RawName] -> (f n l', [RawName])
+ Control.Monad.Foil.Internal: sinkK :: forall {k} (f :: LoT k -> Type) (xs :: LoT (LoT k -> Type)) (as :: LoT (LoT k -> Type)) (bs :: LoT (LoT k -> Type)). GSinkableK f => RenamingsK xs as -> RenamingsK xs bs -> (f :@@: as) -> f :@@: bs
+ Control.Monad.Foil.Internal: sinkabilityProof1 :: forall f (n :: S) (n' :: S). SinkableK f => (Name n -> Name n') -> f n -> f n'
+ Control.Monad.Foil.Internal: sinkabilityProofK :: forall (as :: LoT (S -> k)) (bs :: LoT (S -> k)) r. SinkableK f => RenamingsK as bs -> (f :@@: as) -> (forall (cs :: LoT (S -> k)). () => RenamingsK as cs -> (f :@@: cs) -> r) -> r
+ Control.Monad.Foil.Internal: unsafeSetNameBinders :: forall (n :: S) (l :: S) (l' :: S). HasNameBinders f => f n l -> NameBinders n l' -> f n l'
+ Control.Monad.Foil.Internal.ValidNameBinders: type AndShowDataType (pattern :: t) (n :: Atom d s) (l :: Atom d s) (msg :: ErrorMessage) = 'Text "when tracking Foil scopes for the data type" ':$$: 'Text " " ':<>: ShowSaturatedPatternType pattern n n l l ':$$: msg
+ Control.Monad.Foil.Internal.ValidNameBinders: type ShowKindedScope (oo :: Atom d s) (n :: Atom d s) (ll :: Atom d s) = ShowScope oo n ll ':<>: 'Text " : S"
+ Control.Monad.Foil.Internal.ValidNameBinders: type ShowLocalizeError (msg :: ErrorMessage) (icon :: Natural) (ifield :: Natural) (pattern :: t) (o :: Atom d s) (l :: Atom d s) = AndShowFieldNumber ifield AndShowConNumber icon AndShowDataType pattern o l msg
+ Control.Monad.Foil.Internal.ValidNameBinders: type ShowSaturatedPatternType (pattern :: t) (oo :: Atom d s) (n :: Atom d s) (l :: Atom d s) (ll :: Atom d s) = 'ShowType pattern ':<>: 'Text " " ':<>: ShowScope oo n ll ':<>: 'Text " " ':<>: ShowScope oo l ll
+ Control.Monad.Foil.Internal.ValidNameBinders: type family PutBackLoT (i :: TyVar d s) (c :: s) (bs :: LoT k) :: LoT k
+ Control.Monad.Free.Foil: freeVarsOf :: forall (n :: S) (binder :: S -> S -> Type) (sig :: Type -> Type -> Type). (Distinct n, CoSinkable binder, Bifoldable sig) => AST binder sig n -> [Name n]
+ Control.Monad.Free.Foil: freeVarsOfScopedAST :: forall (n :: S) (binder :: S -> S -> Type) (sig :: Type -> Type -> Type). (Distinct n, CoSinkable binder, Bifoldable sig) => ScopedAST binder sig n -> [Name n]
+ Control.Monad.Free.Foil: instance (Data.Bifunctor.Bifunctor sig, Control.Monad.Foil.Internal.CoSinkable binder, Control.Monad.Foil.Internal.SinkableK binder) => Control.Monad.Foil.Internal.Sinkable (Control.Monad.Free.Foil.AST binder sig)
+ Control.Monad.Free.Foil: instance (Data.Bifunctor.Bifunctor sig, Control.Monad.Foil.Internal.CoSinkable binder, Control.Monad.Foil.Internal.SinkableK binder) => Control.Monad.Foil.Internal.Sinkable (Control.Monad.Free.Foil.ScopedAST binder sig)
+ Control.Monad.Free.Foil: instance (Data.Bifunctor.Bifunctor sig, Control.Monad.Foil.Internal.CoSinkable binder, Control.Monad.Foil.Internal.SinkableK binder) => Control.Monad.Foil.Internal.SinkableK (Control.Monad.Free.Foil.AST binder sig)
+ Control.Monad.Free.Foil: instance (Data.Bifunctor.Bifunctor sig, Control.Monad.Foil.Internal.CoSinkable binder, Control.Monad.Foil.Internal.SinkableK binder) => Control.Monad.Foil.Internal.SinkableK (Control.Monad.Free.Foil.ScopedAST binder sig)
+ Control.Monad.Free.Foil: instance (Data.Bifunctor.Bifunctor sig, Control.Monad.Foil.Internal.CoSinkable binder, Control.Monad.Foil.Internal.SinkableK binder) => Control.Monad.Foil.Relative.RelMonad Control.Monad.Foil.Internal.Name (Control.Monad.Free.Foil.AST binder sig)
+ Control.Monad.Free.Foil: instance Generics.Kind.GenericK (Control.Monad.Free.Foil.AST binder sig)
+ Control.Monad.Free.Foil: instance Generics.Kind.GenericK (Control.Monad.Free.Foil.ScopedAST binder sig)
+ Control.Monad.Free.Foil: unsinkAST :: forall (l :: S) (binder :: S -> S -> Type) (sig :: Type -> Type -> Type) (n :: S). (Distinct l, CoSinkable binder, Bifoldable sig) => Scope n -> AST binder sig l -> Maybe (AST binder sig n)
+ Data.ZipMatchK: ($dmzipMatchWithK) :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (ZipMatchK f, GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs) => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
+ Data.ZipMatchK: class ZipMatchK (f :: k)
+ Data.ZipMatchK: zipMatch1 :: (Traversable f, ZipMatchK f) => f a -> f a' -> Maybe (f (a, a'))
+ Data.ZipMatchK: zipMatch2 :: (Bitraversable f, ZipMatchK f) => f a b -> f a' b' -> Maybe (f (a, a') (b, b'))
+ Data.ZipMatchK: zipMatchK :: forall {k} (f :: k) (as :: LoT k) (bs :: LoT k). (ZipMatchK f, PairMappings as bs) => (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: ZipLoT as bs)
+ Data.ZipMatchK: zipMatchViaChooseLeft :: forall {k} (as :: LoT k) (bs :: LoT k) (cs :: LoT k) a. Mappings as bs cs -> a -> a -> Maybe a
+ Data.ZipMatchK: zipMatchViaEq :: forall {k} a (as :: LoT k) (bs :: LoT k) (cs :: LoT k). Eq a => Mappings as bs cs -> a -> a -> Maybe a
+ Data.ZipMatchK: zipMatchWith1 :: (Traversable f, ZipMatchK f) => (a -> a' -> Maybe a'') -> f a -> f a' -> Maybe (f a'')
+ Data.ZipMatchK: zipMatchWith2 :: (Bitraversable f, ZipMatchK f) => (a -> a' -> Maybe a'') -> (b -> b' -> Maybe b'') -> f a b -> f a' b' -> Maybe (f a'' b'')
+ Data.ZipMatchK: zipMatchWithK :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). ZipMatchK f => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
+ Data.ZipMatchK.Bifunctor: instance (Data.Bitraversable.Bitraversable f, Data.Bitraversable.Bitraversable g, Data.ZipMatchK.Generic.ZipMatchK f, Data.ZipMatchK.Generic.ZipMatchK g) => Data.ZipMatchK.Generic.ZipMatchK (Data.Bifunctor.Product.Product f g)
+ Data.ZipMatchK.Bifunctor: instance (Data.Bitraversable.Bitraversable f, Data.Bitraversable.Bitraversable g, Data.ZipMatchK.Generic.ZipMatchK f, Data.ZipMatchK.Generic.ZipMatchK g) => Data.ZipMatchK.Generic.ZipMatchK (Data.Bifunctor.Sum.Sum f g)
+ Data.ZipMatchK.Bifunctor: instance forall k k1 (f :: k -> k1 -> *) (g :: k -> k1 -> *). Generics.Kind.GenericK (Data.Bifunctor.Product.Product f g)
+ Data.ZipMatchK.Bifunctor: instance forall k k1 (f :: k -> k1 -> *) (g :: k -> k1 -> *). Generics.Kind.GenericK (Data.Bifunctor.Sum.Sum f g)
+ Data.ZipMatchK.Functor: instance (Data.Traversable.Traversable f, Data.Traversable.Traversable g, Data.ZipMatchK.Generic.ZipMatchK f, Data.ZipMatchK.Generic.ZipMatchK g) => Data.ZipMatchK.Generic.ZipMatchK (Data.Functor.Product.Product f g)
+ Data.ZipMatchK.Functor: instance (Data.Traversable.Traversable f, Data.Traversable.Traversable g, Data.ZipMatchK.Generic.ZipMatchK f, Data.ZipMatchK.Generic.ZipMatchK g) => Data.ZipMatchK.Generic.ZipMatchK (Data.Functor.Sum.Sum f g)
+ Data.ZipMatchK.Functor: instance forall k (f :: k -> *) (g :: k -> *). Generics.Kind.GenericK (Data.Functor.Product.Product f g)
+ Data.ZipMatchK.Functor: instance forall k (f :: k -> *) (g :: k -> *). Generics.Kind.GenericK (Data.Functor.Sum.Sum f g)
+ Data.ZipMatchK.Generic: ($dmzipMatchWithK) :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (ZipMatchK f, GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs) => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
+ Data.ZipMatchK.Generic: class GZipMatch (f :: LoT k -> Type) where {
+ Data.ZipMatchK.Generic: class ZipMatchFields (t :: Atom d Type) where {
+ Data.ZipMatchK.Generic: class ZipMatchK (f :: k)
+ Data.ZipMatchK.Generic: genericZipMatchK :: forall {k} (f :: k) (as :: LoT k) (bs :: LoT k). (GenericK f, GZipMatch (RepK f), ReqsZipMatch (RepK f) as bs, PairMappings as bs) => (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: ZipLoT as bs)
+ Data.ZipMatchK.Generic: genericZipMatchWithK :: forall {k} (f :: k) (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs) => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
+ Data.ZipMatchK.Generic: gzipMatchWith :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). (GZipMatch f, ReqsZipMatchWith f as bs cs) => Mappings as bs cs -> f as -> f bs -> Maybe (f cs)
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.GZipMatch GHC.Generics.U1
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.GZipMatch GHC.Generics.V1
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.ZipMatchK (,)
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.ZipMatchK Data.Either.Either
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.ZipMatchK GHC.Base.NonEmpty
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.ZipMatchK GHC.Maybe.Maybe
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.ZipMatchK []
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.ZipMatchK a => Data.ZipMatchK.Generic.ZipMatchK ((,) a)
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.ZipMatchK a => Data.ZipMatchK.Generic.ZipMatchK (Data.Either.Either a)
+ Data.ZipMatchK.Generic: instance Data.ZipMatchK.Generic.ZipMatchK k => Data.ZipMatchK.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Kon k)
+ Data.ZipMatchK.Generic: instance Generics.Kind.GenericK ((,) a)
+ Data.ZipMatchK.Generic: instance Generics.Kind.GenericK (,)
+ Data.ZipMatchK.Generic: instance Generics.Kind.GenericK GHC.Base.NonEmpty
+ Data.ZipMatchK.Generic: instance forall d (a :: Data.PolyKinded.Atom.Atom d (Fcf.Core.Exp (*))). (TypeError ...) => Data.ZipMatchK.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Eval a)
+ Data.ZipMatchK.Generic: instance forall d (c :: Data.PolyKinded.Atom.Atom d GHC.Types.Constraint) (a :: Data.PolyKinded.Atom.Atom d (*)). (TypeError ...) => Data.ZipMatchK.Generic.ZipMatchFields (c 'Data.PolyKinded.Atom.:=>>: a)
+ Data.ZipMatchK.Generic: instance forall d (t :: Data.PolyKinded.Atom.Atom d (*)) (k :: * -> *). (Data.ZipMatchK.Generic.ZipMatchFields t, Data.ZipMatchK.Generic.ZipMatchK k) => Data.ZipMatchK.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Kon k 'Data.PolyKinded.Atom.:@: t)
+ Data.ZipMatchK.Generic: instance forall d (t1 :: Data.PolyKinded.Atom.Atom d (*)) (t2 :: Data.PolyKinded.Atom.Atom d (*)) (k :: * -> * -> *). (Data.ZipMatchK.Generic.ZipMatchFields t1, Data.ZipMatchK.Generic.ZipMatchFields t2, Data.ZipMatchK.Generic.ZipMatchK k) => Data.ZipMatchK.Generic.ZipMatchFields (('Data.PolyKinded.Atom.Kon k 'Data.PolyKinded.Atom.:@: t1) 'Data.PolyKinded.Atom.:@: t2)
+ Data.ZipMatchK.Generic: instance forall d (v :: Data.PolyKinded.Atom.TyVar d (*)). Data.ZipMatchK.Mappings.ApplyMappings v => Data.ZipMatchK.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Var v)
+ Data.ZipMatchK.Generic: instance forall d k1 (f :: Data.PolyKinded.Atom.Atom d (k1 -> *)) (t :: Data.PolyKinded.Atom.Atom d k1). (TypeError ...) => Data.ZipMatchK.Generic.ZipMatchFields (f 'Data.PolyKinded.Atom.:@: t)
+ Data.ZipMatchK.Generic: instance forall d kk (k :: kk -> *) (t :: Data.PolyKinded.Atom.Atom d kk). (TypeError ...) => Data.ZipMatchK.Generic.ZipMatchFields ('Data.PolyKinded.Atom.Kon k 'Data.PolyKinded.Atom.:@: t)
+ Data.ZipMatchK.Generic: instance forall d kk1 kk2 (k :: kk1 -> kk2 -> *) (t1 :: Data.PolyKinded.Atom.Atom d kk1) (t2 :: Data.PolyKinded.Atom.Atom d kk2). (TypeError ...) => Data.ZipMatchK.Generic.ZipMatchFields (('Data.PolyKinded.Atom.Kon k 'Data.PolyKinded.Atom.:@: t1) 'Data.PolyKinded.Atom.:@: t2)
+ Data.ZipMatchK.Generic: instance forall d1 d (a :: Data.PolyKinded.Atom.Atom (d1 -> d) (*)). (TypeError ...) => Data.ZipMatchK.Generic.ZipMatchFields ('Data.PolyKinded.Atom.ForAll a)
+ Data.ZipMatchK.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) (c :: Data.PolyKinded.Atom.Atom k GHC.Types.Constraint). Data.ZipMatchK.Generic.GZipMatch f => Data.ZipMatchK.Generic.GZipMatch (c Generics.Kind.:=>: f)
+ Data.ZipMatchK.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) (g :: Data.PolyKinded.LoT k -> *). (Data.ZipMatchK.Generic.GZipMatch f, Data.ZipMatchK.Generic.GZipMatch g) => Data.ZipMatchK.Generic.GZipMatch (f GHC.Generics.:*: g)
+ Data.ZipMatchK.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) (g :: Data.PolyKinded.LoT k -> *). (Data.ZipMatchK.Generic.GZipMatch f, Data.ZipMatchK.Generic.GZipMatch g) => Data.ZipMatchK.Generic.GZipMatch (f GHC.Generics.:+: g)
+ Data.ZipMatchK.Generic: instance forall k (f :: Data.PolyKinded.LoT k -> *) i (c :: GHC.Generics.Meta). Data.ZipMatchK.Generic.GZipMatch f => Data.ZipMatchK.Generic.GZipMatch (GHC.Generics.M1 i c f)
+ Data.ZipMatchK.Generic: instance forall k (t :: Data.PolyKinded.Atom.Atom k (*)). Data.ZipMatchK.Generic.ZipMatchFields t => Data.ZipMatchK.Generic.GZipMatch (Generics.Kind.Field t)
+ Data.ZipMatchK.Generic: instance forall k1 k2 (f :: Data.PolyKinded.LoT (k2 -> k1) -> *). (TypeError ...) => Data.ZipMatchK.Generic.GZipMatch (Generics.Kind.Exists k2 f)
+ Data.ZipMatchK.Generic: type ReqsZipMatch (f :: LoT k -> Type) (as :: LoT k) (bs :: LoT k) = ReqsZipMatchWith f as bs ZipLoT as bs
+ Data.ZipMatchK.Generic: type ReqsZipMatchFieldsWith (t :: Atom d Type) (as :: LoT d) (bs :: LoT d) (cs :: LoT d);
+ Data.ZipMatchK.Generic: type ReqsZipMatchWith (f :: LoT k -> Type) (as :: LoT k) (bs :: LoT k) (cs :: LoT k);
+ Data.ZipMatchK.Generic: zipMatchFieldsWith :: forall (as :: LoT d) (bs :: LoT d) (cs :: LoT d). (ZipMatchFields t, ReqsZipMatchFieldsWith t as bs cs) => Mappings as bs cs -> Field t as -> Field t bs -> Maybe (Field t cs)
+ Data.ZipMatchK.Generic: zipMatchWithK :: forall (as :: LoT k) (bs :: LoT k) (cs :: LoT k). ZipMatchK f => Mappings as bs cs -> (f :@@: as) -> (f :@@: bs) -> Maybe (f :@@: cs)
+ Data.ZipMatchK.Generic: }
+ Data.ZipMatchK.Mappings: [:^:] :: forall {k1} a b c (as1 :: LoT k1) (bs1 :: LoT k1) (cs1 :: LoT k1). (a -> b -> Maybe c) -> Mappings as1 bs1 cs1 -> Mappings (a ':&&: as1) (b ':&&: bs1) (c ':&&: cs1)
+ Data.ZipMatchK.Mappings: [M0] :: Mappings 'LoT0 'LoT0 'LoT0
+ Data.ZipMatchK.Mappings: applyMappings :: forall (as :: LoT d) (bs :: LoT d) (cs :: LoT d). ApplyMappings v => Mappings as bs cs -> Interpret ('Var v) as -> Interpret ('Var v) bs -> Maybe (Interpret ('Var v) cs)
+ Data.ZipMatchK.Mappings: class ApplyMappings (v :: TyVar d Type)
+ Data.ZipMatchK.Mappings: class PairMappings (as :: LoT k) (bs :: LoT k)
+ Data.ZipMatchK.Mappings: data Mappings (as :: LoT k) (bs :: LoT k) (cs :: LoT k)
+ Data.ZipMatchK.Mappings: infixr 5 :^:
+ Data.ZipMatchK.Mappings: instance Data.ZipMatchK.Mappings.ApplyMappings 'Data.PolyKinded.Atom.VZ
+ Data.ZipMatchK.Mappings: instance Data.ZipMatchK.Mappings.PairMappings 'Data.PolyKinded.LoT0 'Data.PolyKinded.LoT0
+ Data.ZipMatchK.Mappings: instance forall ks (as :: Data.PolyKinded.LoT ks) (bs :: Data.PolyKinded.LoT ks) a b. Data.ZipMatchK.Mappings.PairMappings as bs => Data.ZipMatchK.Mappings.PairMappings (a 'Data.PolyKinded.:&&: as) (b 'Data.PolyKinded.:&&: bs)
+ Data.ZipMatchK.Mappings: instance forall tys (v :: Data.PolyKinded.Atom.TyVar tys (*)) ty. Data.ZipMatchK.Mappings.ApplyMappings v => Data.ZipMatchK.Mappings.ApplyMappings ('Data.PolyKinded.Atom.VS v)
+ Data.ZipMatchK.Mappings: pairA :: Applicative f => a -> b -> f (a, b)
+ Data.ZipMatchK.Mappings: pairMappings :: PairMappings as bs => Mappings as bs (ZipLoT as bs)
+ Data.ZipMatchK.Mappings: type family ZipLoT (as :: LoT k) (bs :: LoT k) :: LoT k
- Control.Monad.Free.Foil: alphaEquiv :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool
+ Control.Monad.Free.Foil: alphaEquiv :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bitraversable sig, ZipMatchK sig, Distinct n, UnifiablePattern binder, SinkableK binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool
- Control.Monad.Free.Foil: alphaEquivRefreshed :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool
+ Control.Monad.Free.Foil: alphaEquivRefreshed :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bitraversable sig, ZipMatchK sig, Distinct n, UnifiablePattern binder, SinkableK binder) => Scope n -> AST binder sig n -> AST binder sig n -> Bool
- Control.Monad.Free.Foil: alphaEquivScoped :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Bifoldable sig, ZipMatch sig, Distinct n, UnifiablePattern binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n -> Bool
+ Control.Monad.Free.Foil: alphaEquivScoped :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bitraversable sig, ZipMatchK sig, Distinct n, UnifiablePattern binder, SinkableK binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n -> Bool
- Control.Monad.Free.Foil: refreshAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder) => Scope n -> AST binder sig n -> AST binder sig n
+ Control.Monad.Free.Foil: refreshAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder, SinkableK binder) => Scope n -> AST binder sig n -> AST binder sig n
- Control.Monad.Free.Foil: refreshScopedAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n
+ Control.Monad.Free.Foil: refreshScopedAST :: forall (sig :: Type -> Type -> Type) (n :: S) (binder :: S -> S -> Type). (Bifunctor sig, Distinct n, CoSinkable binder, SinkableK binder) => Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n
- Control.Monad.Free.Foil: substitute :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o
+ Control.Monad.Free.Foil: substitute :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder, SinkableK binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o
- Control.Monad.Free.Foil: substitutePattern :: forall (sig :: Type -> Type -> Type) (o :: S) binder' (binder :: S -> S -> Type) (n :: S) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder', CoSinkable binder) => Scope o -> Substitution (AST binder sig) n o -> binder' n i -> [AST binder sig o] -> AST binder sig i -> AST binder sig o
+ Control.Monad.Free.Foil: substitutePattern :: forall (sig :: Type -> Type -> Type) (o :: S) binder' (binder :: S -> S -> Type) (n :: S) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder', CoSinkable binder, SinkableK binder) => Scope o -> Substitution (AST binder sig) n o -> binder' n i -> [AST binder sig o] -> AST binder sig i -> AST binder sig o
- Control.Monad.Free.Foil: substituteRefreshed :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o
+ Control.Monad.Free.Foil: substituteRefreshed :: forall (sig :: Type -> Type -> Type) (o :: S) (binder :: S -> S -> Type) (i :: S). (Bifunctor sig, Distinct o, CoSinkable binder, SinkableK binder) => Scope o -> Substitution (AST binder sig) i o -> AST binder sig i -> AST binder sig o
- Control.Monad.Free.Foil: unsafeEqAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig, UnifiablePattern binder, Distinct n, Distinct l) => AST binder sig n -> AST binder sig l -> Bool
+ Control.Monad.Free.Foil: unsafeEqAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bitraversable sig, ZipMatchK sig, UnifiablePattern binder, Distinct n, Distinct l) => AST binder sig n -> AST binder sig l -> Bool
- Control.Monad.Free.Foil: unsafeEqScopedAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bifoldable sig, ZipMatch sig, UnifiablePattern binder, Distinct n, Distinct l) => ScopedAST binder sig n -> ScopedAST binder sig l -> Bool
+ Control.Monad.Free.Foil: unsafeEqScopedAST :: forall (sig :: Type -> Type -> Type) (binder :: S -> S -> Type) (n :: S) (l :: S). (Bitraversable sig, ZipMatchK sig, UnifiablePattern binder, Distinct n, Distinct l) => ScopedAST binder sig n -> ScopedAST binder sig l -> Bool
Files
- ChangeLog.md +77/−0
- free-foil.cabal +29/−25
- src/Control/Monad/Foil.hs +2/−0
- src/Control/Monad/Foil/Internal.hs +431/−6
- src/Control/Monad/Foil/Internal/ValidNameBinders.hs +180/−0
- src/Control/Monad/Free/Foil.hs +61/−36
- src/Control/Monad/Free/Foil/Generic.hs +0/−196
- src/Control/Monad/Free/Foil/TH.hs +0/−2
- src/Control/Monad/Free/Foil/TH/PatternSynonyms.hs +1/−1
- src/Control/Monad/Free/Foil/TH/ZipMatch.hs +0/−57
- src/Data/ZipMatchK.hs +80/−0
- src/Data/ZipMatchK/Bifunctor.hs +35/−0
- src/Data/ZipMatchK/Functor.hs +34/−0
- src/Data/ZipMatchK/Generic.hs +193/−0
- src/Data/ZipMatchK/Mappings.hs +60/−0
ChangeLog.md view
@@ -1,5 +1,82 @@ # CHANGELOG for `free-foil` +# 0.3.0 — 2026-07-14++This release makes generic deriving the default way to instantiate the library:+`Sinkable`, `CoSinkable`, `UnifiablePattern` and `ZipMatchK` can now all be+derived via [`kind-generics`](https://hackage.haskell.org/package/kind-generics),+so a user-defined pattern normally needs no hand-written instances at all.+The cost is one breaking change, described first.++## Breaking changes++- The `ZipMatch` class is **removed** in favour of the kind-polymorphic `ZipMatchK`,+ and the modules are reorganised (see [#30](https://github.com/fizruk/free-foil/pull/30)):++ - `Control.Monad.Free.Foil.Generic` is replaced by `Data.ZipMatchK`+ (with `Data.ZipMatchK.Bifunctor`, `Data.ZipMatchK.Functor`,+ `Data.ZipMatchK.Generic` and `Data.ZipMatchK.Mappings`);+ - `Control.Monad.Free.Foil.TH.ZipMatch` (and its `deriveZipMatch`) is removed,+ and `Control.Monad.Free.Foil.TH` no longer re-exports it.++ To migrate, delete the `ZipMatch` instances and any `deriveZipMatch` splices,+ and keep only the `ZipMatchK` ones. Where you had++ ```haskell+ import Control.Monad.Free.Foil.Generic++ instance ZipMatchK a => ZipMatchK (TermSig a)+ instance ZipMatchK a => ZipMatch (TermSig a) where zipMatch = genericZipMatch2+ ```++ the second instance simply goes away:++ ```haskell+ import Data.ZipMatchK++ instance ZipMatchK a => ZipMatchK (TermSig a)+ ```++ `ZipMatchK` is derived generically, so the signature needs a `GenericK` instance+ (`deriveGenericK ''TermSig` from `kind-generics-th`). Note that `kind-generics-th`+ is not on Stackage, and is not a dependency of this library: a package using+ `deriveGenericK` must depend on it itself.++- α-equivalence and refreshing now ask for more of the binder: `alphaEquiv`,+ `alphaEquivRefreshed`, `refreshAST` and `refreshScopedAST` require+ `SinkableK binder` (and `ZipMatchK sig` in place of `ZipMatch sig`).+ For binders and patterns generated by our Template Haskell, or derived generically,+ this constraint is already satisfied and no change is needed.++## Generic deriving of patterns (see [#31](https://github.com/fizruk/free-foil/pull/31))++- New `SinkableK` class, generalising both `Sinkable` and `CoSinkable`:+ a type `f n₁ n₂ … nₖ` is treated as a generalised binder with variables and terms+ in scopes `n₁, n₂, …, nₖ`. Generic (kind-polymorphic) implementations are provided+ for `sinkabilityProof` and `coSinkabilityProof`, so `Sinkable` and `CoSinkable`+ instances can be left empty.+- New `HasNameBinders` class, generalising access to the nested `NameBinder`s of a pattern.+ This is what makes a *generic* `withPattern` possible, so user-defined patterns+ no longer need a hand-written traversal.+- `UnifiablePattern` now has a default implementation via `CoSinkable`,+ so `instance UnifiablePattern MyPattern` normally suffices.+- Malformed user-defined patterns are now rejected with a readable type error+ by a separate generic check (`GValidNameBinders`), instead of failing obscurely+ deeper in the machinery. Terms (and other types) are allowed in patterns,+ as long as the binders are threaded correctly.++## New functions (see [#32](https://github.com/fizruk/free-foil/pull/32))++- `unsinkAST` — unsink an `AST` from a larger scope into a smaller one, when possible.+- `freeVarsOf` and `freeVarsOfScopedAST` — collect the free variables of an `AST`.+- `nameMapToScope` — recover a `Scope` from a `NameMap`.+- `NameMap` is now a `Functor`, `Foldable` and `Traversable`.++## Fixes++- `GValidNameBinders` no longer rejects a valid constructor that equates its scopes+ and carries more than one field (substitution now recurses through sums and products).+ # 0.2.0 — 2024-10-27 - Generate [`COMPLETE` pragma](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/pragmas.html#complete-pragmas) in `mkPatternSynonyms` (see [#26](https://github.com/fizruk/free-foil/pull/26))
free-foil.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.37.0.+-- This file has been generated from package.yaml by hpack version 0.39.1. -- -- see: https://github.com/sol/hpack name: free-foil-version: 0.2.0+version: 0.3.0 synopsis: Efficient Type-Safe Capture-Avoiding Substitution for Free (Scoped Monads) description: Please see the README on GitHub at <https://github.com/fizruk/free-foil#readme> category: Parsing@@ -31,6 +31,7 @@ Control.Monad.Foil Control.Monad.Foil.Example Control.Monad.Foil.Internal+ Control.Monad.Foil.Internal.ValidNameBinders Control.Monad.Foil.Relative Control.Monad.Foil.TH Control.Monad.Foil.TH.MkFoilData@@ -40,27 +41,30 @@ Control.Monad.Foil.TH.Util Control.Monad.Free.Foil Control.Monad.Free.Foil.Example- Control.Monad.Free.Foil.Generic Control.Monad.Free.Foil.TH Control.Monad.Free.Foil.TH.Convert Control.Monad.Free.Foil.TH.MkFreeFoil Control.Monad.Free.Foil.TH.PatternSynonyms Control.Monad.Free.Foil.TH.Signature- Control.Monad.Free.Foil.TH.ZipMatch+ Data.ZipMatchK+ Data.ZipMatchK.Bifunctor+ Data.ZipMatchK.Functor+ Data.ZipMatchK.Generic+ Data.ZipMatchK.Mappings other-modules: Paths_free_foil hs-source-dirs: src ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -optP-Wno-nonportable-include-path build-depends:- array >=0.5.3.0+ array >=0.5.3.0 && <0.6 , base >=4.7 && <5- , bifunctors- , containers- , deepseq- , kind-generics >=0.5.0- , template-haskell >=2.21.0.0- , text >=1.2.3.1+ , bifunctors >=5.5 && <5.7+ , containers >=0.6 && <0.9+ , deepseq >=1.4 && <1.6+ , kind-generics >=0.5.0 && <0.6+ , template-haskell >=2.21.0.0 && <2.24+ , text >=1.2.3.1 && <2.2 default-language: Haskell2010 test-suite doctests@@ -71,16 +75,16 @@ test/doctests ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -optP-Wno-nonportable-include-path build-depends:- array >=0.5.3.0+ array >=0.5.3.0 && <0.6 , base >=4.7 && <5- , bifunctors- , containers- , deepseq+ , bifunctors >=5.5 && <5.7+ , containers >=0.6 && <0.9+ , deepseq >=1.4 && <1.6 , doctest-parallel , free-foil- , kind-generics >=0.5.0- , template-haskell >=2.21.0.0- , text >=1.2.3.1+ , kind-generics >=0.5.0 && <0.6+ , template-haskell >=2.21.0.0 && <2.24+ , text >=1.2.3.1 && <2.2 default-language: Haskell2010 test-suite spec@@ -92,13 +96,13 @@ test ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -optP-Wno-nonportable-include-path -threaded -rtsopts -with-rtsopts=-N build-depends:- array >=0.5.3.0+ array >=0.5.3.0 && <0.6 , base >=4.7 && <5- , bifunctors- , containers- , deepseq+ , bifunctors >=5.5 && <5.7+ , containers >=0.6 && <0.9+ , deepseq >=1.4 && <1.6 , free-foil- , kind-generics >=0.5.0- , template-haskell >=2.21.0.0- , text >=1.2.3.1+ , kind-generics >=0.5.0 && <0.6+ , template-haskell >=2.21.0.0 && <2.24+ , text >=1.2.3.1 && <2.2 default-language: Haskell2010
src/Control/Monad/Foil.hs view
@@ -35,8 +35,10 @@ unsinkName, unsinkNamePattern, -- * Safe (co)sinking and renaming+ SinkableK(..), Sinkable(..), CoSinkable(..),+ HasNameBinders(getNameBinders), sink, extendRenaming, extendNameBinderRenaming,
src/Control/Monad/Foil/Internal.hs view
@@ -1,16 +1,25 @@+{-# OPTIONS_GHC -Wno-missing-methods #-} -- disabled to avoid overlapping type instances+{-# OPTIONS_GHC -Wno-overlapping-patterns -Wno-inaccessible-code #-} -- disabled because I think GHC is wrong+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE BlockArguments #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-incomplete-patterns #-} {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}@@ -36,15 +45,20 @@ -- — the number of bits in an 'Int' (32 or 64). module Control.Monad.Foil.Internal where -import Control.DeepSeq (NFData (..))-import Data.Coerce (coerce)+import Control.DeepSeq (NFData (..))+import Data.Bifunctor+import Data.Coerce (coerce) import Data.IntMap-import qualified Data.IntMap as IntMap+import qualified Data.IntMap as IntMap import Data.IntSet-import qualified Data.IntSet as IntSet-import Data.Kind (Type)+import qualified Data.IntSet as IntSet+import Data.Kind (Type)+import qualified Data.Type.Equality as Type+import Generics.Kind import Unsafe.Coerce +import Control.Monad.Foil.Internal.ValidNameBinders+ -- * Safe types and operations -- | 'S' is a data kind of scope indices.@@ -563,7 +577,17 @@ class CoSinkable pattern => UnifiablePattern pattern where -- | Unify two patterns and decide which binders need to be renamed. unifyPatterns :: Distinct n => pattern n l -> pattern n r -> UnifyNameBinders pattern n l r+ default unifyPatterns+ :: (CoSinkable pattern, Distinct n)+ => pattern n l -> pattern n r -> UnifyNameBinders pattern n l r+ unifyPatterns l r = coerce (unifyPatterns (nameBinderListOf l) (nameBinderListOf r)) +instance UnifiablePattern NameBinderList where+ unifyPatterns NameBinderListEmpty NameBinderListEmpty = SameNameBinders emptyNameBinders+ unifyPatterns (NameBinderListCons x xs) (NameBinderListCons y ys) =+ case (assertDistinct x, assertDistinct y) of+ (Distinct, Distinct) -> unifyNameBinders x y `andThenUnifyPatterns` (xs, ys)+ -- | Unification of values in patterns. -- By default, 'Eq' instance is used, but it may be useful to ignore -- some data in pattens (such as location annotations).@@ -599,6 +623,10 @@ -> e n -- ^ Expression with free variables in scope @n@. -> e l + default sinkabilityProof+ :: (GenericK e, GSinkableK (RepK e)) => (Name n -> Name l) -> e n -> e l+ sinkabilityProof rename = toK . gsinkabilityProof1 rename . fromK+ -- | Sinking a 'Name' is as simple as applying the renaming. instance Sinkable Name where sinkabilityProof rename = rename@@ -688,6 +716,14 @@ -- ^ A continuation, accepting an extended renaming from @l@ to @l'@ (which itself extends @n'@) -- and a (possibly refreshed) pattern that extends @n'@ to @l'@. -> r+ default coSinkabilityProof+ :: (GenericK pattern, GSinkableK (RepK pattern))+ => (Name n -> Name n')+ -> pattern n l+ -> (forall l'. (Name l -> Name l') -> pattern n' l' -> r)+ -> r+ coSinkabilityProof rename p cont = gsinkabilityProof2 rename (fromK @_ @pattern p) $ \rename' p' ->+ cont rename' (toK @_ @pattern p') -- | Generalized processing of a pattern. --@@ -707,6 +743,16 @@ -> (forall o'. DExt o o' => f n l o o' -> pattern o o' -> r) -- ^ Continuation, accepting result for the entire pattern and a (possibly refreshed) pattern. -> r+ default withPattern+ :: (Distinct o, GenericK pattern, GValidNameBinders pattern (RepK pattern), GHasNameBinders (RepK pattern))+ => (forall x y z r'. Distinct z => Scope z -> NameBinder x y -> (forall z'. DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r')+ -> (forall x z z'. DExt z z' => f x x z z')+ -> (forall x y y' z z' z''. (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'')+ -> Scope o+ -> pattern n l+ -> (forall o'. DExt o o' => f n l o o' -> pattern o o' -> r)+ -> r+ withPattern = gunsafeWithPatternViaHasNameBinders -- | Auxiliary data structure for collecting name binders. Used in 'nameBinderListOf'. newtype WithNameBinderList r n l (o :: S) (o' :: S) = WithNameBinderList (NameBinderList l r -> NameBinderList n r)@@ -808,7 +854,7 @@ -- * 'Name' maps -- | A /total/ map from names in scope @n@ to elements of type @a@.-newtype NameMap (n :: S) a = NameMap { getNameMap :: IntMap a }+newtype NameMap (n :: S) a = NameMap { getNameMap :: IntMap a } deriving (Functor, Foldable, Traversable) -- | An empty map belongs in the empty scope. emptyNameMap :: NameMap VoidS a@@ -818,6 +864,10 @@ nameMapToSubstitution :: NameMap i (e o) -> Substitution e i o nameMapToSubstitution (NameMap m) = (UnsafeSubstitution m) +-- | Convert a 'NameMap' of expressions into a 'Scope'.+nameMapToScope :: NameMap n a -> Scope n+nameMapToScope (NameMap m) = UnsafeScope (IntMap.keysSet m)+ -- | Extend a map with multiple mappings (by repeatedly applying 'addNameBinder'). -- -- Note that the input list is expected to have __at least__ the same number of elements@@ -907,3 +957,378 @@ class InjectName (e :: S -> Type) where -- | Inject names into expressions. injectName :: Name n -> e n++-- * Kind-polymorphic sinkability++data RenamingsK (as :: LoT k) (bs :: LoT k) where+ RNil :: RenamingsK LoT0 LoT0+ RCons :: (Name a -> Name b) -> RenamingsK as bs -> RenamingsK (a :&&: as) (b :&&: bs)+ RSkip :: RenamingsK as bs -> RenamingsK (k :&&: as) (k :&&: bs)++class SinkableK (f :: S -> k) where+ sinkabilityProofK+ :: forall as bs r.+ RenamingsK as bs+ -> f :@@: as+ -> (forall cs. RenamingsK as cs -> f :@@: cs -> r)+ -> r+ default sinkabilityProofK :: forall as bs r.+ (GenericK f, GSinkableK (RepK f))+ => RenamingsK as bs+ -> f :@@: as+ -> (forall cs. RenamingsK as cs -> f :@@: cs -> r)+ -> r+ sinkabilityProofK rename e cont =+ gsinkabilityProofK rename (fromK @_ @f e) $ \rename' e' ->+ cont rename' (toK @_ @f e')++sinkK :: GSinkableK f => RenamingsK xs as -> RenamingsK xs bs -> f :@@: as -> f :@@: bs+sinkK _ _ = unsafeCoerce++instance SinkableK Name where+ sinkabilityProofK renameK@(RCons rename RNil) name cont = cont renameK (rename name)+instance SinkableK NameBinder where+ sinkabilityProofK (RCons _ RNil) (UnsafeNameBinder name) cont =+ cont (RCons unsafeCoerce RNil) (UnsafeNameBinder name)+instance SinkableK NameBinders where+ sinkabilityProofK (RCons _ RNil) (UnsafeNameBinders s) cont =+ cont (RCons unsafeCoerce RNil) (UnsafeNameBinders s)++instance GenericK NameBinderList where+ type RepK NameBinderList = ((Var0 :~~: Var1) :=>: U1) :+: Exists S+ (Field (NameBinder :$: Var1 :@: Var0) :*: Field (NameBinderList :$: Var0 :@: Var2))+ toK (L1 (SuchThat U1)) = NameBinderListEmpty+ toK (R1 (Exists (Field x :*: Field xs))) = NameBinderListCons x xs+ fromK NameBinderListEmpty = L1 (SuchThat U1)+ fromK (NameBinderListCons x xs) = R1 (Exists (Field x :*: Field xs))++instance GenericK V2 where+ type RepK V2 = V1+ toK _v1 = error "absurd: Generics.Kind.V1"+ fromK = absurd2++instance GenericK U2 where+ type RepK U2 = ((Var0 :~~: Var1) :=>: U1)+ toK (SuchThat U1) = U2+ fromK U2 = SuchThat U1++instance SinkableK NameBinderList+instance SinkableK V2+instance SinkableK U2++sinkabilityProof1 :: SinkableK f => (Name n -> Name n') -> f n -> f n'+sinkabilityProof1 rename e = sinkabilityProofK (RCons rename RNil) e $ \_ e' -> unsafeCoerce e'++gsinkabilityProof1 :: GSinkableK f => (Name n -> Name n') -> f (n :&&: LoT0) -> f (n' :&&: LoT0)+gsinkabilityProof1 rename e = gsinkabilityProofK (RCons rename RNil) e $ \_ e' -> unsafeCoerce e'++gsinkabilityProof2+ :: forall f n n' l r. GSinkableK f+ => (Name n -> Name n') -> f (n :&&: l :&&: LoT0)+ -> (forall l'. (Name l -> Name l') -> f (n' :&&: l' :&&: LoT0) -> r)+ -> r+gsinkabilityProof2 rename e cont =+ gsinkabilityProofK (RCons rename (RCons id RNil)) e $ \case+ RCons (_ :: Name n -> Name n'') (RCons rename' RNil) -> \e' ->+ case unsafeCoerce (Type.Refl :: n' Type.:~: n') :: n' Type.:~: n'' of+ Type.Refl -> cont rename' e'++gsinkabilityProofK' :: GSinkableK f => RenamingsK as bs -> f as -> f bs+gsinkabilityProofK' renameK e = gsinkabilityProofK renameK e $ \_ e' -> unsafeCoerce e'++class GSinkableK p where+ gsinkabilityProofK+ :: forall as bs r.+ RenamingsK as bs+ -> p as+ -> (forall cs. RenamingsK as cs -> p cs -> r)+ -> r++gsinkK :: GSinkableK f => RenamingsK xs as -> RenamingsK xs bs -> f as -> f bs+gsinkK _ _ = unsafeCoerce++instance GSinkableK V1 where+ gsinkabilityProofK irename _v1 cont =+ cont irename (error "absurd: Generics.Kind.V1")++instance GSinkableK U1 where+ gsinkabilityProofK irename U1 cont =+ cont irename U1++instance GSinkableK f => GSinkableK (M1 i c f) where+ gsinkabilityProofK irename (M1 x) cont =+ gsinkabilityProofK irename x $ \irename' x' ->+ cont irename' (M1 x')++instance (GSinkableK f, GSinkableK g) => GSinkableK (f :+: g) where+ gsinkabilityProofK irename (L1 x) cont =+ gsinkabilityProofK irename x $ \irename' x' ->+ cont irename' (L1 x')+ gsinkabilityProofK irename (R1 x) cont =+ gsinkabilityProofK irename x $ \irename' x' ->+ cont irename' (R1 x')++instance (GSinkableK f, GSinkableK g) => GSinkableK (f :*: g) where+ gsinkabilityProofK irename (x :*: y) cont =+ gsinkabilityProofK irename x $ \irename' x' ->+ gsinkabilityProofK irename' y $ \irename'' y' ->+ cont irename'' (gsinkK irename' irename'' x' :*: y')++instance GSinkableK f => GSinkableK (Exists S f) where+ gsinkabilityProofK irename (Exists x) cont =+ gsinkabilityProofK (RCons id irename) x $ \case+ RCons _ irename' -> \x' ->+ cont irename' (Exists x')++instance {-# OVERLAPPABLE #-} GSinkableK f => GSinkableK (Exists k f) where+ gsinkabilityProofK irename (Exists x) cont =+ gsinkabilityProofK (RSkip irename) x $ \case+ RSkip irename' -> \x' ->+ cont irename' (Exists x')++instance GSinkableK f => GSinkableK ((a :~~: b) :=>: f) where+ gsinkabilityProofK irename (SuchThat x) cont =+ gsinkabilityProofK irename x $ \(irename' :: RenamingsK as cs) x' ->+ -- this is sort of safe...+ case unsafeCoerce (Type.Refl :: Interpret a cs Type.:~: Interpret a cs) :: Interpret a cs Type.:~: Interpret b cs of+ Type.Refl -> cont irename' (SuchThat x')++instance GSinkableK (Field (Kon a)) where+ gsinkabilityProofK irename (Field x) cont =+ cont irename (Field x)++instance GSinkableK (Field (Var a)) where+ gsinkabilityProofK irename (Field x) cont =+ cont irename (Field (unsafeCoerce x)) -- FIXME: unsafeCoerce?++instance (SinkableK f, ExtractRenamingK i) => GSinkableK (Field (Kon f :@: Var i)) where+ gsinkabilityProofK irename (Field x) cont =+ sinkabilityProofK (RCons (extractRenamingK @_ @i irename) RNil) x $ \case+ RCons rename' RNil -> \x' ->+ cont (putBackRenamingK @_ @i rename' irename) (Field (unsafeCoerce x')) -- unsafeCoerce?++instance SinkableK (f a) => GSinkableK (Field (Kon f :@: Kon a :@: Var0)) where+ gsinkabilityProofK irename@(RCons _ RNil) (Field x) cont =+ sinkabilityProofK irename x $ \rename' x' ->+ cont rename' (Field x')++instance SinkableK (f a b) => GSinkableK (Field (Kon f :@: Kon a :@: Kon b :@: Var0)) where+ gsinkabilityProofK irename@(RCons _ RNil) (Field x) cont =+ sinkabilityProofK irename x $ \rename' x' ->+ cont rename' (Field x')++class ExtractRenamingK (i :: TyVar k S) where+ extractRenamingK :: forall (as :: LoT k) (bs :: LoT k).+ RenamingsK as bs -> Name (Interpret (Var i) as) -> Name (Interpret (Var i) bs)+ putBackRenamingK :: forall c (as :: LoT k) (bs :: LoT k).+ (Name (Interpret (Var i) as) -> Name c)+ -> RenamingsK as bs+ -> RenamingsK as (PutBackLoT i c bs)++instance ExtractRenamingK VZ where+ extractRenamingK (RCons f _fs) = f+ putBackRenamingK f (RCons _ gs) = RCons f gs++instance ExtractRenamingK x => ExtractRenamingK (VS x) where+ extractRenamingK (RCons _f fs) = extractRenamingK @_ @x fs+ putBackRenamingK f (RCons g gs) = RCons g (putBackRenamingK @_ @x f gs)++extractTwoRenamingsK :: forall k (i :: TyVar k S) (j :: TyVar k S) (as :: LoT k) (bs :: LoT k).+ (ExtractRenamingK i, ExtractRenamingK j)+ => RenamingsK as bs+ -> RenamingsK+ (Interpret (Var i) as :&&: Interpret (Var j) as :&&: LoT0)+ (Interpret (Var i) bs :&&: Interpret (Var j) bs :&&: LoT0)+extractTwoRenamingsK irename =+ (RCons (extractRenamingK @_ @i irename) (RCons (extractRenamingK @_ @j irename) RNil))++putBackTwoRenamingsK :: forall k (i :: TyVar k S) (j :: TyVar k S) c1 c2 (as :: LoT k) (bs :: LoT k).+ (ExtractRenamingK i, ExtractRenamingK j)+ => RenamingsK+ (Interpret (Var i) as :&&: Interpret (Var j) as :&&: LoT0)+ (c1 :&&: c2 :&&: LoT0)+ -> RenamingsK as bs+ -> RenamingsK as (PutBackLoT j c2 (PutBackLoT i c1 bs))+putBackTwoRenamingsK (RCons f1 (RCons f2 RNil)) rename+ = putBackRenamingK @_ @j f2 (putBackRenamingK @_ @i f1 rename)++instance (SinkableK f, ExtractRenamingK i, ExtractRenamingK j) => GSinkableK (Field (Kon f :@: Var (i :: TyVar k S) :@: Var (j :: TyVar k S))) where+ gsinkabilityProofK irename (Field x) cont =+ sinkabilityProofK (extractTwoRenamingsK @_ @i @j irename) x $ \rename' x' ->+ case rename' of+ RCons _ (RCons _ RNil) ->+ cont (putBackTwoRenamingsK @_ @i @j rename' irename)+ (Field (unsafeCoerce x')) -- FIXME: can we do better than unsafeCoerce?++instance (Functor f, GSinkableK (Field x)) => GSinkableK (Field (Kon f :@: x)) where+ gsinkabilityProofK irename (Field x) cont =+ cont irename (Field (fmap+ (unField . gsinkabilityProofK' @(Field x) irename . Field)+ x))++instance (Bifunctor f, GSinkableK (Field x), GSinkableK (Field y)) => GSinkableK (Field (Kon f :@: x :@: y)) where+ gsinkabilityProofK irename (Field x) cont =+ cont irename (Field (bimap+ (unField . gsinkabilityProofK' @(Field x) irename . Field)+ (unField . gsinkabilityProofK' @(Field y) irename . Field)+ x))++-- * Kind-polymorphic types with binders++-- ** Generic version of 'withPattern'++-- | Generic generalized processing of a pattern via 'GHasNameBinders'.+--+-- This can be used as a default implementation of 'withPattern'.+gunsafeWithPatternViaHasNameBinders+ :: forall pattern f o n l r.+ (Distinct o, GenericK pattern, GValidNameBinders pattern (RepK pattern), GHasNameBinders (RepK pattern))+ => (forall x y z r'. Distinct z => Scope z -> NameBinder x y -> (forall z'. DExt z z' => f x y z z' -> NameBinder z z' -> r') -> r')+ -- ^ Processing of a single 'NameBinder', this will be applied to each binder in a pattern.+ -> (forall x z z'. DExt z z' => f x x z z')+ -- ^ Result in case no binders are present. This can be seen as scope-indexed 'mempty'.+ -> (forall x y y' z z' z''. (DExt z z', DExt z' z'') => f x y z z' -> f y y' z' z'' -> f x y' z z'')+ -- ^ Composition of results for nested binders/patterns. This can be seen as scope-indexed 'mappend'.+ -> Scope o+ -- ^ Ambient scope.+ -> pattern n l+ -- ^ Pattern to process.+ -> (forall o'. DExt o o' => f n l o o' -> pattern o o' -> r)+ -- ^ Continuation, accepting result for the entire pattern and a (possibly refreshed) pattern.+ -> r+gunsafeWithPatternViaHasNameBinders withBinder id_ comp_ scope pat cont =+ withPattern withBinder id_ comp_ scope (ggetNameBinders pat) $ \result binders ->+ cont result (gunsafeSetNameBinders (unsafeCoerce pat) binders) -- FIXME: safer version++-- ** Manipulating nested 'NameBinder's+-- | If @'HasNameBinders' f@, then @f n l@ is expected to act as a binder,+-- introducing into scope @n@ some local variables, extending it to scope @l@.+-- This class allows to extract and modify the set of binders.+class HasNameBinders f where+ -- | Extract a set of binders from a pattern.+ getNameBinders :: f n l -> NameBinders n l+ getNameBinders = UnsafeNameBinders . IntSet.fromList . getNameBindersRaw++ -- | Replace binders in a pattern.+ --+ -- This function is unsafe, because it does not check if the new set of binders+ -- has the same size. It can therefore crash at runtime.+ --+ -- You should probably not use this.+ -- This is only used for 'gunsafeWithPatternViaHasNameBinders', which is then safe to use.+ unsafeSetNameBinders :: f n l -> NameBinders n l' -> f n l'+ unsafeSetNameBinders e (UnsafeNameBinders m) = fst (reallyUnsafeSetNameBindersRaw e (IntSet.toList m))++ -- | Extract 'RawName's of all binders occurring in a pattern.+ getNameBindersRaw :: f n l -> [RawName]+ default getNameBindersRaw :: forall n l. (GenericK f, GHasNameBinders (RepK f)) => f n l -> [RawName]+ getNameBindersRaw = ggetNameBindersRaw . fromK @_ @f @(n :&&: l :&&: LoT0)++ -- | This is a version of 'unsafeSetNameBinders'+ -- that takes in a list of 'RawName's.+ --+ -- It does not check if the given list has enough elements.+ -- It does not check if the raw names are fresh in the scope @n@.+ -- It does not check if the raw names given are distinct.+ --+ -- You should never use this. This is only used for generic implementation of 'HasNameBinders'.+ reallyUnsafeSetNameBindersRaw :: f n l -> [RawName] -> (f n l', [RawName])+ default reallyUnsafeSetNameBindersRaw :: forall n l l'. (GenericK f, GValidNameBinders f (RepK f), GHasNameBinders (RepK f)) => f n l -> [RawName] -> (f n l', [RawName])+ reallyUnsafeSetNameBindersRaw e names =+ let (e', names') = greallyUnsafeSetNameBindersRaw (fromK @_ @f @(n :&&: l :&&: LoT0) e) names+ in (toK @_ @f @(n :&&: l' :&&: LoT0) e', names')++instance HasNameBinders NameBinder where+ getNameBindersRaw (UnsafeNameBinder (UnsafeName name)) = [name]+ reallyUnsafeSetNameBindersRaw _ (name:names) = (UnsafeNameBinder (UnsafeName name), names)++instance HasNameBinders NameBinderList++-- ** Generic++ggetNameBinders :: forall f n l. (GenericK f, GHasNameBinders (RepK f)) => f n l -> NameBinders n l+ggetNameBinders = UnsafeNameBinders . IntSet.fromList . ggetNameBindersRaw . fromK @_ @f @(n :&&: l :&&: LoT0)++gunsafeSetNameBinders :: forall f n l l'. (GenericK f, GValidNameBinders f (RepK f), GHasNameBinders (RepK f)) => f n l -> NameBinders n l' -> f n l'+gunsafeSetNameBinders e (UnsafeNameBinders m) = toK @_ @f @(n :&&: l' :&&: LoT0) $+ fst (greallyUnsafeSetNameBindersRaw (fromK @_ @f @(n :&&: l :&&: LoT0) e) (IntSet.toList m))++class GHasNameBinders f where+ ggetNameBindersRaw :: f as -> [RawName]+ greallyUnsafeSetNameBindersRaw :: f as -> [RawName] -> (f bs, [RawName])++instance GHasNameBinders V1 where+ ggetNameBindersRaw _ = error "absurd: Generics.Kind.V1"+ greallyUnsafeSetNameBindersRaw _ _ = error "absurd: Generics.Kind.V1"+instance GHasNameBinders U1 where+ ggetNameBindersRaw U1 = []+ greallyUnsafeSetNameBindersRaw U1 names = (U1, names)++instance (GHasNameBinders f, GHasNameBinders g) => GHasNameBinders (f :+: g) where+ ggetNameBindersRaw (L1 x) = ggetNameBindersRaw x+ ggetNameBindersRaw (R1 x) = ggetNameBindersRaw x++ greallyUnsafeSetNameBindersRaw (L1 x) names = first L1 (greallyUnsafeSetNameBindersRaw x names)+ greallyUnsafeSetNameBindersRaw (R1 x) names = first R1 (greallyUnsafeSetNameBindersRaw x names)++-- | FIXME: this is, perhaps, the most "unsafe" place for the user+-- since it does not reject "parallel" binders:+--+-- data BadPattern n l = BadPattern (NameBinder n l) (NameBinder n l)+--+-- This instance will treat both binders in the same way as "nested":+--+-- data GoodPattern n l = forall i. GoodPattern (NameBinder n i) (NameBinder i l)+--+-- However, Template Haskell code at the moment will never generate "parallel" binders,+-- and the very user is unlikely to misuse this instance, since "parallel" binders+-- require extra effort to support it.+--+-- Still, it would be better to detect and reject any "parallel" or otherwise improper binders.+instance (GHasNameBinders f, GHasNameBinders g) => GHasNameBinders (f :*: g) where+ ggetNameBindersRaw (x :*: y) = ggetNameBindersRaw x <> ggetNameBindersRaw y+ greallyUnsafeSetNameBindersRaw (x :*: y) names =+ let (x', names') = greallyUnsafeSetNameBindersRaw x names+ (y', names'') = greallyUnsafeSetNameBindersRaw y names'+ in (x' :*: y', names'')++instance GHasNameBinders f => GHasNameBinders (M1 i c f) where+ ggetNameBindersRaw (M1 x) = ggetNameBindersRaw x+ greallyUnsafeSetNameBindersRaw (M1 x) names =+ let (x', names') = greallyUnsafeSetNameBindersRaw x names+ in (M1 x', names')++instance GHasNameBinders f => GHasNameBinders (Var i :~~: Var j :=>: f) where+ ggetNameBindersRaw (SuchThat x) = ggetNameBindersRaw x++ greallyUnsafeSetNameBindersRaw :: forall as bs. (Var i :~~: Var j :=>: f) as -> [RawName] -> ((Var i :~~: Var j :=>: f) bs, [RawName])+ greallyUnsafeSetNameBindersRaw (SuchThat x) names =+ -- this is sort of safe...+ case unsafeCoerce (Type.Refl :: Interpret (Var i) bs Type.:~: Interpret (Var i) bs) :: Interpret (Var i) bs Type.:~: Interpret (Var j) bs of+ Type.Refl ->+ let (x', names') = greallyUnsafeSetNameBindersRaw x names+ in (SuchThat x', names')++instance GHasNameBinders f => GHasNameBinders (Exists k f) where+ ggetNameBindersRaw (Exists x) = ggetNameBindersRaw x+ greallyUnsafeSetNameBindersRaw (Exists x) names =+ let (x', names') = greallyUnsafeSetNameBindersRaw x names+ in (Exists x', names')++instance GHasNameBinders (Field (Kon a)) where+ ggetNameBindersRaw (Field _x) = []+ greallyUnsafeSetNameBindersRaw (Field x) names = (Field x, names)++instance GHasNameBinders (Field (Var x)) where+ ggetNameBindersRaw (Field _x) = []+ greallyUnsafeSetNameBindersRaw (Field x) names = (Field (unsafeCoerce x), names) -- FIXME: unsafeCoerce?++instance GHasNameBinders (Field (Kon f :@: Var i)) where+ ggetNameBindersRaw (Field _x) = []+ greallyUnsafeSetNameBindersRaw (Field x) names = (Field (unsafeCoerce x), names) -- FIXME: unsafeCoerce?++instance HasNameBinders f => GHasNameBinders (Field (Kon f :@: Var i :@: Var j)) where+ ggetNameBindersRaw (Field x) = getNameBindersRaw x+ greallyUnsafeSetNameBindersRaw (Field x) names =+ let (x', names') = reallyUnsafeSetNameBindersRaw x names+ in (Field (unsafeCoerce x'), names') -- FIXME: safer version?
+ src/Control/Monad/Foil/Internal/ValidNameBinders.hs view
@@ -0,0 +1,180 @@+{-# LANGUAGE StandaloneKindSignatures #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE DataKinds #-}+module Control.Monad.Foil.Internal.ValidNameBinders where++import Data.Kind (Type, Constraint)+import GHC.TypeError+import GHC.TypeLits+import Generics.Kind+import qualified GHC.Generics as GHC++type SubstInRepK :: TyVar d k -> Atom d k -> (LoT d -> Type) -> LoT d -> Type+type family SubstInRepK i atom f where+ SubstInRepK i atom V1 = V1+ SubstInRepK i atom U1 = U1+ SubstInRepK i atom (M1 info c f) = M1 info c (SubstInRepK i atom f)+ SubstInRepK i atom (Field field) = Field (SubstInAtom i atom field)+ SubstInRepK i atom (f :+: g) = SubstInRepK i atom f :+: SubstInRepK i atom g+ SubstInRepK i atom (f :*: g) = SubstInRepK i atom f :*: SubstInRepK i atom g+ SubstInRepK i atom f =+ TypeError+ ('Text "cannot substitute variable"+ :$$: 'Text " " :<>: 'ShowType (Var i)+ :$$: 'Text "with atom"+ :$$: 'Text " " :<>: 'ShowType atom+ :$$: 'Text "in"+ :$$: 'Text " " :<>: 'ShowType f)++type SubstInAtom :: TyVar d k -> Atom d k -> Atom d k1 -> Atom d k1+type family SubstInAtom i atom f where+ SubstInAtom i atom (Var i) = atom+ SubstInAtom i atom (Var j) = Var j+ SubstInAtom i atom (Kon a) = Kon a+ SubstInAtom i atom (f :@: x) = SubstInAtom i atom f :@: SubstInAtom i atom x+ -- SubstInAtom i atom atom' = atom'+ SubstInAtom i atom atom' =+ TypeError+ ('Text "cannot substitute variable"+ :$$: 'Text " " :<>: 'ShowType (Var i)+ :$$: 'Text "with atom"+ :$$: 'Text " " :<>: 'ShowType atom+ :$$: 'Text "in an atom"+ :$$: 'Text " " :<>: 'ShowType atom')++type ShowKindedScope oo n ll = ShowScope oo n ll :<>: 'Text " : S"++type ShowScope :: Atom d s -> Atom d s -> Atom d s -> ErrorMessage+type family ShowScope oo n ll where+ ShowScope oo ll ll = 'Text "innerScope"+ ShowScope oo oo ll = 'Text "outerScope"+ ShowScope oo n ll = ShowScopeN 1 n++type ShowScopeN :: Natural -> Atom d s -> ErrorMessage+type family ShowScopeN i n where+ ShowScopeN i (Var VZ) = 'Text "scope" :<>: 'ShowType i+ ShowScopeN i (Var (VS x)) = ShowScopeN (i + 1) (Var x)++type ShowSaturatedPatternType pattern oo n l ll =+ 'ShowType pattern :<>: 'Text " " :<>: ShowScope oo n ll :<>: 'Text " " :<>: ShowScope oo l ll++type GInnerScopeOfAtom :: ErrorMessage -> Nat -> Nat -> (s -> s -> Type) -> Atom d Type -> Atom d s -> Atom d s -> Atom d s -> Atom d s+type family GInnerScopeOfAtom msg icon ifield pattern atom oo n ll where+ GInnerScopeOfAtom msg icon ifield pattern (Kon f :@: n :@: l) oo n ll = l+ GInnerScopeOfAtom msg icon ifield pattern (Kon f :@: o :@: i) oo n ll =+ TypeError+ ('Text "Unexpected Foil scope extension in the binder/pattern"+ :$$: 'Text " " :<>: ShowSaturatedPatternType f oo o i ll+ :$$: 'Text "the binder/pattern tries to extend scope"+ :$$: 'Text " " :<>: ShowKindedScope oo o ll+ :$$: 'Text "to scope"+ :$$: 'Text " " :<>: ShowKindedScope oo i ll+ :$$: 'Text "but it is expected to extend the current (outer) scope"+ :$$: 'Text " " :<>: ShowKindedScope oo n ll+ :$$: ShowLocalizeError msg icon ifield pattern oo ll+ )+ GInnerScopeOfAtom msg icon ifield pattern atom oo n ll = n++type SameInnerScope :: ErrorMessage -> Nat -> (s -> s -> Type) -> Atom k s -> Atom k s -> Atom k s+type family SameInnerScope msg icon pattern n l where+ SameInnerScope msg icon pattern l l = l+ SameInnerScope msg icon pattern n l =+ TypeError+ ('Text "Unexpected extended (inner) Foil scope in the data type"+ :$$: 'Text " " :<>: ShowSaturatedPatternType pattern n n l l+ :$$: 'Text "expecting extended (inner) scope to be"+ :$$: 'Text " " :<>: ShowKindedScope n l l+ :$$: 'Text "but the inferred extended (inner) scope is"+ :$$: 'Text " " :<>: ShowKindedScope n n l+ :$$: ShowLocalizeError msg icon 0 pattern n l+ )++type GValidNameBinders :: (s -> s -> Type) -> (LoT (s -> s -> Type) -> Type) -> Constraint+type family GValidNameBinders pattern f :: Constraint where+ GValidNameBinders pattern (f :: LoT (s -> s -> Type) -> Type) =+ (GInnerScopeOfRepK ('Text "") 0 0 pattern f Var0 Var0 Var1)+ ~ (Var1 :: Atom (s -> s -> Type) s)++type AtomSucc :: Atom d k1 -> Atom (k -> d) k1+type family AtomSucc atom where+ AtomSucc (Var i) = Var (VS i)++type AtomUnSucc :: ErrorMessage -> Nat -> (s -> s -> Type) -> Atom d s -> Atom d s -> Atom (k -> d) k1 -> Atom d k1+type family AtomUnSucc msg icon pattern oo ll atom where+ AtomUnSucc msg icon pattern oo ll (Var (VS i)) = Var i+ AtomUnSucc msg icon pattern oo ll (Var VZ) = TypeError+ ('Text "Intermediate scope escapes existential quantification for data type"+ :$$: ShowLocalizeError msg icon 0 pattern oo ll+ )++type family First x y where+ First (Var x) (Var y) = Var x++type family AndShowFieldNumber ifield msg where+ AndShowFieldNumber 0 msg = msg+ AndShowFieldNumber n msg =+ 'Text "when checking field number " :<>: 'ShowType n+ :$$: msg++type family AndShowConNumber icon msg where+ AndShowConNumber 0 msg = msg+ AndShowConNumber n msg =+ 'Text "when checking constructor number " :<>: 'ShowType n+ :$$: msg++type AndShowDataType pattern n l msg =+ 'Text "when tracking Foil scopes for the data type"+ :$$: 'Text " " :<>: ShowSaturatedPatternType pattern n n l l+ :$$: msg++type ShowLocalizeError msg icon ifield pattern o l =+ AndShowFieldNumber ifield+ (AndShowConNumber icon+ (AndShowDataType pattern o l+ msg))++type family CountCons f where+ CountCons (f :+: g) = CountCons f + CountCons g+ CountCons (M1 GHC.C c f) = 1++type family CountFields f where+ CountFields (f :*: g) = CountFields f + CountFields g+ CountFields (M1 GHC.S c f) = 1++type GInnerScopeOfRepK :: ErrorMessage -> Nat -> Nat -> (s -> s -> Type) -> (LoT k -> Type) -> Atom k s -> Atom k s -> Atom k s -> Atom k s+type family GInnerScopeOfRepK msg icon ifield pattern f o n l where+ GInnerScopeOfRepK msg icon ifield pattern V1 o n l = l+ GInnerScopeOfRepK msg icon ifield pattern U1 o n l = n+ GInnerScopeOfRepK msg icon ifield pattern (M1 GHC.C c f) o n l =+ GInnerScopeOfRepK msg icon 1 pattern f o n l+ GInnerScopeOfRepK msg icon ifield pattern (M1 GHC.D c f) o n l =+ GInnerScopeOfRepK msg 1 ifield pattern f o n l+ GInnerScopeOfRepK msg icon ifield pattern (M1 i c f) o n l =+ GInnerScopeOfRepK msg icon ifield pattern f o n l+ GInnerScopeOfRepK msg icon ifield pattern (f :+: g) o n l = First+ (SameInnerScope msg icon pattern (GInnerScopeOfRepK msg icon ifield pattern f o n l) l)+ (SameInnerScope msg icon pattern (GInnerScopeOfRepK msg (icon + CountCons f) ifield pattern g o n l) l)+ GInnerScopeOfRepK msg icon ifield pattern (f :*: g) o n l =+ GInnerScopeOfRepK msg icon (ifield + CountFields f) pattern g o+ (GInnerScopeOfRepK msg icon ifield pattern f o n l) l+ GInnerScopeOfRepK msg icon ifield pattern (Var i :~~: Var j :=>: f) o n l =+ GInnerScopeOfRepK msg icon ifield pattern (SubstInRepK i (Var j) f)+ (SubstInAtom i (Var j) o) (SubstInAtom i (Var j) n) (SubstInAtom i (Var j) l)+ GInnerScopeOfRepK msg icon ifield pattern (Exists k f) o n l =+ AtomUnSucc msg icon pattern o l+ (GInnerScopeOfRepK msg icon ifield pattern f (AtomSucc o) (AtomSucc n) (AtomSucc l))+ GInnerScopeOfRepK msg icon ifield pattern (Field atom) o n l = GInnerScopeOfAtom msg icon ifield pattern atom o n l+ GInnerScopeOfRepK msg icon ifield pattern f o n l =+ TypeError+ ('Text "Unsupported structure in a binder/pattern"+ :$$: 'Text " " :<>: 'ShowType f+ :$$: ShowLocalizeError msg icon 0 pattern n l)++type PutBackLoT :: TyVar d s -> s -> LoT k -> LoT k+type family PutBackLoT i c bs where+ PutBackLoT VZ c (b :&&: bs) = c :&&: bs+ PutBackLoT (VS x) c (b :&&: bs) = b :&&: PutBackLoT x c bs
src/Control/Monad/Free/Foil.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-}@@ -23,13 +25,18 @@ import qualified Control.Monad.Foil.Internal as Foil import qualified Control.Monad.Foil.Relative as Foil import Data.Bifoldable+import Data.Bitraversable import Data.Bifunctor-import Data.Bifunctor.Sum+import Data.ZipMatchK+import qualified Generics.Kind as Kind+import Generics.Kind (GenericK(..), Field, Exists, Var0, Var1, (:$:), Atom((:@:), Kon), (:+:), (:*:)) import Data.Coerce (coerce) import Data.Map (Map) import qualified Data.Map as Map+import Data.Maybe (mapMaybe) import Data.Monoid (All (..)) import GHC.Generics (Generic)+import Unsafe.Coerce (unsafeCoerce) -- | Scoped term under a (single) name binder. data ScopedAST binder sig n where@@ -50,15 +57,26 @@ deriving instance (forall x y. NFData (binder x y), forall scope term. (NFData scope, NFData term) => NFData (sig scope term)) => NFData (AST binder sig n) -instance (Bifunctor sig, Foil.CoSinkable binder) => Foil.Sinkable (AST binder sig) where- sinkabilityProof rename = \case- Var name -> Var (rename name)- Node node -> Node (bimap f (Foil.sinkabilityProof rename) node)- where- f (ScopedAST binder body) =- Foil.extendRenaming rename binder $ \rename' binder' ->- ScopedAST binder' (Foil.sinkabilityProof rename' body)+instance GenericK (ScopedAST binder sig) where+ type RepK (ScopedAST binder sig) =+ Exists Foil.S+ (Field (Kon binder :@: Var1 :@: Var0) :*: Field (Kon AST :@: Kon binder :@: Kon sig :@: Var0))+ toK (Kind.Exists (Kind.Field binder Kind.:*: Kind.Field ast)) = ScopedAST binder ast+ fromK (ScopedAST binder ast) = Kind.Exists (Kind.Field binder Kind.:*: Kind.Field ast) +instance GenericK (AST binder sig) where+ type RepK (AST binder sig) =+ Field (Foil.Name :$: Var0)+ :+: Field (sig+ :$: (Kon ScopedAST :@: Kon binder :@: Kon sig :@: Var0)+ :@: (Kon AST :@: Kon binder :@: Kon sig :@: Var0))++instance (Bifunctor sig, Foil.CoSinkable binder, Foil.SinkableK binder) => Foil.Sinkable (ScopedAST binder sig)+instance (Bifunctor sig, Foil.CoSinkable binder, Foil.SinkableK binder) => Foil.Sinkable (AST binder sig)++instance (Bifunctor sig, Foil.CoSinkable binder, Foil.SinkableK binder) => Foil.SinkableK (ScopedAST binder sig)+instance (Bifunctor sig, Foil.CoSinkable binder, Foil.SinkableK binder) => Foil.SinkableK (AST binder sig)+ instance Foil.InjectName (AST binder sig) where injectName = Var @@ -66,7 +84,7 @@ -- | Substitution for free (scoped monads). substitute- :: (Bifunctor sig, Foil.Distinct o, Foil.CoSinkable binder)+ :: (Bifunctor sig, Foil.Distinct o, Foil.CoSinkable binder, Foil.SinkableK binder) => Foil.Scope o -> Foil.Substitution (AST binder sig) i o -> AST binder sig i@@ -91,7 +109,7 @@ -- -- In general, 'substitute' is more efficient since it does not always refresh binders. substituteRefreshed- :: (Bifunctor sig, Foil.Distinct o, Foil.CoSinkable binder)+ :: (Bifunctor sig, Foil.Distinct o, Foil.CoSinkable binder, Foil.SinkableK binder) => Foil.Scope o -> Foil.Substitution (AST binder sig) i o -> AST binder sig i@@ -108,7 +126,8 @@ in ScopedAST binder' body' -- | @'AST' sig@ is a monad relative to 'Foil.Name'.-instance (Bifunctor sig, Foil.CoSinkable binder) => Foil.RelMonad Foil.Name (AST binder sig) where+instance (Bifunctor sig, Foil.CoSinkable binder, Foil.SinkableK binder)+ => Foil.RelMonad Foil.Name (AST binder sig) where rreturn = Var rbind scope term subst = case term of@@ -124,7 +143,7 @@ -- | Substitution for a single generalized pattern. substitutePattern- :: (Bifunctor sig, Foil.Distinct o, Foil.CoSinkable binder', Foil.CoSinkable binder)+ :: (Bifunctor sig, Foil.Distinct o, Foil.CoSinkable binder', Foil.CoSinkable binder, Foil.SinkableK binder) => Foil.Scope o -- ^ Resulting scope. -> Foil.Substitution (AST binder sig) n o -- ^ Environment mapping names in scope @n@. -> binder' n i -- ^ Binders that extend scope @n@ to scope @i@.@@ -140,7 +159,7 @@ -- | Refresh (force) all binders in a term, minimizing the used indices. refreshAST- :: (Bifunctor sig, Foil.Distinct n, Foil.CoSinkable binder)+ :: (Bifunctor sig, Foil.Distinct n, Foil.CoSinkable binder, Foil.SinkableK binder) => Foil.Scope n -> AST binder sig n -> AST binder sig n@@ -149,7 +168,7 @@ Node t -> Node (bimap (refreshScopedAST scope) (refreshAST scope) t) -- | Similar to `refreshAST`, but for scoped terms.-refreshScopedAST :: (Bifunctor sig, Foil.Distinct n, Foil.CoSinkable binder)+refreshScopedAST :: (Bifunctor sig, Foil.Distinct n, Foil.CoSinkable binder, Foil.SinkableK binder) => Foil.Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n@@ -165,7 +184,7 @@ -- Compared to 'alphaEquiv', this function may perform some unnecessary -- changes of bound variables when the binders are the same on both sides. alphaEquivRefreshed- :: (Bifunctor sig, Bifoldable sig, ZipMatch sig, Foil.Distinct n, Foil.UnifiablePattern binder)+ :: (Bitraversable sig, ZipMatchK sig, Foil.Distinct n, Foil.UnifiablePattern binder, Foil.SinkableK binder) => Foil.Scope n -> AST binder sig n -> AST binder sig n@@ -178,21 +197,21 @@ -- Compared to 'alphaEquivRefreshed', this function might skip unnecessary -- changes of bound variables when both binders in two matching scoped terms coincide. alphaEquiv- :: (Bifunctor sig, Bifoldable sig, ZipMatch sig, Foil.Distinct n, Foil.UnifiablePattern binder)+ :: (Bitraversable sig, ZipMatchK sig, Foil.Distinct n, Foil.UnifiablePattern binder, Foil.SinkableK binder) => Foil.Scope n -> AST binder sig n -> AST binder sig n -> Bool alphaEquiv _scope (Var x) (Var y) = x == coerce y alphaEquiv scope (Node l) (Node r) =- case zipMatch l r of+ case zipMatch2 l r of Nothing -> False Just tt -> getAll (bifoldMap (All . uncurry (alphaEquivScoped scope)) (All . uncurry (alphaEquiv scope)) tt) alphaEquiv _ _ _ = False -- | Same as 'alphaEquiv' but for scoped terms. alphaEquivScoped- :: (Bifunctor sig, Bifoldable sig, ZipMatch sig, Foil.Distinct n, Foil.UnifiablePattern binder)+ :: (Bitraversable sig, ZipMatchK sig, Foil.Distinct n, Foil.UnifiablePattern binder, Foil.SinkableK binder) => Foil.Scope n -> ScopedAST binder sig n -> ScopedAST binder sig n@@ -237,20 +256,20 @@ -- scope extensions under binders (which might happen due to substitution -- under a binder in absence of name conflicts). unsafeEqAST- :: (Bifoldable sig, ZipMatch sig, Foil.UnifiablePattern binder, Foil.Distinct n, Foil.Distinct l)+ :: (Bitraversable sig, ZipMatchK sig, Foil.UnifiablePattern binder, Foil.Distinct n, Foil.Distinct l) => AST binder sig n -> AST binder sig l -> Bool unsafeEqAST (Var x) (Var y) = x == coerce y unsafeEqAST (Node t1) (Node t2) =- case zipMatch t1 t2 of+ case zipMatch2 t1 t2 of Nothing -> False Just tt -> getAll (bifoldMap (All . uncurry unsafeEqScopedAST) (All . uncurry unsafeEqAST) tt) unsafeEqAST _ _ = False -- | A version of 'unsafeEqAST' for scoped terms. unsafeEqScopedAST- :: (Bifoldable sig, ZipMatch sig, Foil.UnifiablePattern binder, Foil.Distinct n, Foil.Distinct l)+ :: (Bitraversable sig, ZipMatchK sig, Foil.UnifiablePattern binder, Foil.Distinct n, Foil.Distinct l) => ScopedAST binder sig n -> ScopedAST binder sig l -> Bool@@ -260,20 +279,6 @@ (Foil.Distinct, Foil.Distinct) -> body1 `unsafeEqAST` body2 ] --- ** Syntactic matching (unification)---- | Perform one-level matching for the two (non-variable) terms.-class ZipMatch sig where- zipMatch- :: sig scope term -- ^ Left non-variable term.- -> sig scope' term' -- ^ Right non-variable term.- -> Maybe (sig (scope, scope') (term, term'))--instance (ZipMatch f, ZipMatch g) => ZipMatch (Sum f g) where- zipMatch (L2 f) (L2 f') = L2 <$> zipMatch f f'- zipMatch (R2 g) (R2 g') = R2 <$> zipMatch g g'- zipMatch _ _ = Nothing- -- * Converting to and from free foil -- ** Convert to free foil@@ -389,3 +394,23 @@ ScopedAST binder body -> ( makePattern binder , makeScoped (convertFromAST fromSig fromVar makePattern makeScoped f body))++-- ** Unsinking AST++-- | Unsink an AST from a larger scope to a smaller scope.+unsinkAST :: (Foil.Distinct l, Foil.CoSinkable binder, Bifoldable sig) => Foil.Scope n -> AST binder sig l -> Maybe (AST binder sig n)+unsinkAST scope term+ | all (`Foil.member` scope) (freeVarsOf term) = Just (unsafeCoerce term)+ | otherwise = Nothing++-- | Get the free variables of an AST.+freeVarsOf :: (Foil.Distinct n, Foil.CoSinkable binder, Bifoldable sig) => AST binder sig n -> [Foil.Name n]+freeVarsOf = \case+ Var name -> [name]+ Node node -> bifoldMap freeVarsOfScopedAST freeVarsOf node++-- | Get the free variables of a scoped AST.+freeVarsOfScopedAST :: (Foil.Distinct n, Foil.CoSinkable binder, Bifoldable sig) => ScopedAST binder sig n -> [Foil.Name n]+freeVarsOfScopedAST (ScopedAST binder body) =+ case Foil.assertDistinct binder of+ Foil.Distinct -> mapMaybe (Foil.unsinkNamePattern binder) (freeVarsOf body)
− src/Control/Monad/Free/Foil/Generic.hs
@@ -1,196 +0,0 @@-{-# OPTIONS_GHC -Wno-missing-methods #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneKindSignatures #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-}-module Control.Monad.Free.Foil.Generic where--import Data.Kind (Constraint, Type)-import Generics.Kind-import Generics.Kind.Examples ()-import GHC.TypeError--type ZipLoT :: LoT k -> LoT k -> LoT k-type family ZipLoT as bs where- ZipLoT LoT0 LoT0 = LoT0- ZipLoT (a :&&: as) (b :&&: bs) = ((a, b) :&&: ZipLoT as bs)--type Mappings :: LoT k -> LoT k -> LoT k -> Type-data Mappings (as :: LoT k) (bs :: LoT k) (cs :: LoT k) where- M0 :: Mappings LoT0 LoT0 LoT0- (:^:) :: (a -> b -> Maybe c) -> Mappings as bs cs -> Mappings (a :&&: as) (b :&&: bs) (c :&&: cs)--class PairMappings (as :: LoT k) (bs :: LoT k) where- pairMappings :: Mappings as bs (ZipLoT as bs)--instance PairMappings LoT0 LoT0 where- pairMappings = M0--instance PairMappings as bs => PairMappings ((a :: Type) :&&: as) ((b :: Type) :&&: bs) where- pairMappings = (\x y -> Just (x, y)) :^: pairMappings--class ApplyMappings (v :: TyVar d Type) where- applyMappings :: forall (as :: LoT d) (bs :: LoT d) (cs :: LoT d).- Mappings as bs cs -> Interpret (Var v) as -> Interpret (Var v) bs -> Maybe (Interpret (Var v) cs)--instance ApplyMappings (VZ :: TyVar (Type -> tys) Type) where- applyMappings (f :^: _) x y = f x y--instance ApplyMappings v => ApplyMappings (VS v :: TyVar (ty -> tys) Type) where- applyMappings (_ :^: fs) x y = applyMappings @_ @v fs x y--genericZipMatchK :: forall f as bs.- (GenericK f, GZipMatch (RepK f), ReqsZipMatch (RepK f) as bs, PairMappings as bs)- => f :@@: as -> f :@@: bs -> Maybe (f :@@: (ZipLoT as bs))-genericZipMatchK = genericZipMatchWithK @f @as @bs pairMappings--genericZipMatchWithK :: forall f as bs cs.- (GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs)- => Mappings as bs cs -> f :@@: as -> f :@@: bs -> Maybe (f :@@: cs)-genericZipMatchWithK mappings x y = toK @_ @f @cs <$> gzipMatchWith mappings- (fromK @_ @f @as x)- (fromK @_ @f @bs y)--genericZipMatch2- :: forall sig scope scope' term term'.- (GenericK sig, GZipMatch (RepK sig), ReqsZipMatch (RepK sig) (scope :&&: term :&&: 'LoT0) (scope' :&&: term' :&&: 'LoT0))- => sig scope term -> sig scope' term' -> Maybe (sig (scope, scope') (term, term'))-genericZipMatch2 = genericZipMatchK @sig @(scope :&&: term :&&: 'LoT0) @(scope' :&&: term' :&&: 'LoT0)--zipMatchK :: forall f as bs. (ZipMatchK f, PairMappings as bs) => f :@@: as -> f :@@: bs -> Maybe (f :@@: ZipLoT as bs)-zipMatchK = zipMatchWithK @_ @f @as @bs pairMappings--class ZipMatchK (f :: k) where- zipMatchWithK :: forall as bs cs. Mappings as bs cs -> f :@@: as -> f :@@: bs -> Maybe (f :@@: cs)- default zipMatchWithK :: forall as bs cs.- (GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs)- => Mappings as bs cs -> f :@@: as -> f :@@: bs -> Maybe (f :@@: cs)- zipMatchWithK = genericZipMatchWithK @f @as @bs @cs--zipMatchViaEq :: Eq a => Mappings as bs cs -> a -> a -> Maybe a-zipMatchViaEq _ x y- | x == y = Just x- | otherwise = Nothing--zipMatchViaChooseLeft :: Mappings as bs cs -> a -> a -> Maybe a-zipMatchViaChooseLeft _ x _ = Just x---- instance ZipMatchK (,) -- missing GenericK instance upstream-instance ZipMatchK []-instance ZipMatchK Maybe-instance ZipMatchK Either-instance ZipMatchK a => ZipMatchK (Either a)--type ReqsZipMatch f as bs = ReqsZipMatchWith f as bs (ZipLoT as bs)-class GZipMatch (f :: LoT k -> Type) where- type ReqsZipMatchWith f (as :: LoT k) (bs :: LoT k) (cs :: LoT k) :: Constraint- gzipMatchWith :: ReqsZipMatchWith f as bs cs => Mappings as bs cs -> f as -> f bs -> Maybe (f cs)--instance GZipMatch V1 where- type ReqsZipMatchWith V1 as bs cs = ()- gzipMatchWith _ _ _ = error "impossible: Generics.Kind.V1 value!" -- FIXME: should be absurd--instance GZipMatch U1 where- type ReqsZipMatchWith U1 as bs cs = ()- gzipMatchWith _ U1 U1 = Just U1--instance GZipMatch f => GZipMatch (M1 i c f) where- type ReqsZipMatchWith (M1 i c f) as bs cs = ReqsZipMatchWith f as bs cs- gzipMatchWith g (M1 x) (M1 y) = M1 <$> gzipMatchWith g x y--instance (GZipMatch f, GZipMatch g) => GZipMatch (f :+: g) where- type ReqsZipMatchWith (f :+: g) as bs cs = (ReqsZipMatchWith f as bs cs, ReqsZipMatchWith g as bs cs)- gzipMatchWith g (L1 x) (L1 y) = L1 <$> gzipMatchWith g x y- gzipMatchWith g (R1 x) (R1 y) = R1 <$> gzipMatchWith g x y- gzipMatchWith _ _ _ = Nothing--instance (GZipMatch f, GZipMatch g) => GZipMatch (f :*: g) where- type ReqsZipMatchWith (f :*: g) as bs cs = (ReqsZipMatchWith f as bs cs, ReqsZipMatchWith g as bs cs)- gzipMatchWith g (x :*: y) (x' :*: y') =- liftA2 (:*:) (gzipMatchWith g x x') (gzipMatchWith g y y')--instance ZipMatchFields t => GZipMatch (Field t) where- type ReqsZipMatchWith (Field t) as bs cs = ReqsZipMatchFieldsWith t as bs cs- gzipMatchWith f x y = zipMatchFieldsWith f x y--instance GZipMatch f => GZipMatch (c :=>: f) where- type ReqsZipMatchWith (c :=>: f) as bs cs = (ReqsZipMatchWith f as bs cs, Interpret c cs)- -- really we want = (Interpret c as, Interpret c bs) => (ReqsZipMatch f as bs, Interpret c (ZipLoT as bs))- gzipMatchWith g (SuchThat x) (SuchThat y) = SuchThat <$> gzipMatchWith g x y--instance TypeError ('Text "Existentials are not supported")- => GZipMatch (Exists k f) where- type ReqsZipMatchWith (Exists k f) as bs cs = TypeError ('Text "Existentials are not supported")- gzipMatchWith = undefined--class ZipMatchFields (t :: Atom d Type) where- type ReqsZipMatchFieldsWith t (as :: LoT d) (bs :: LoT d) (cs :: LoT d) :: Constraint- zipMatchFieldsWith :: ReqsZipMatchFieldsWith t as bs cs => Mappings as bs cs -> Field t as -> Field t bs -> Maybe (Field t cs)--instance ApplyMappings v => ZipMatchFields (Var v) where- -- this is always true, but GHC is not smart enough to know that, I think- type ReqsZipMatchFieldsWith (Var v) as bs cs = () -- InterpretVar v cs ~ (InterpretVar v as, InterpretVar v bs))- zipMatchFieldsWith g (Field x) (Field y) = Field <$> applyMappings @_ @v g x y--instance ZipMatchK k => ZipMatchFields (Kon k) where- type ReqsZipMatchFieldsWith (Kon k) as bs cs = ()- zipMatchFieldsWith _ (Field l) (Field r) = Field <$> zipMatchWithK @_ @k M0 l r--instance (ZipMatchFields t, ZipMatchK k) => ZipMatchFields (Kon k :@: t) where- type ReqsZipMatchFieldsWith (Kon k :@: t) as bs cs = ReqsZipMatchFieldsWith t as bs cs-- zipMatchFieldsWith :: forall as bs cs. ReqsZipMatchFieldsWith (Kon k :@: t) as bs cs =>- Mappings as bs cs -> Field (Kon k :@: t) as -> Field (Kon k :@: t) bs -> Maybe (Field (Kon k :@: t) cs)- zipMatchFieldsWith g (Field l) (Field r) =- Field <$> zipMatchWithK @_ @k @(Interpret t as :&&: LoT0) @(Interpret t bs :&&: LoT0) @(Interpret t cs :&&: LoT0)- ((\ll rr -> unField @t <$> zipMatchFieldsWith g (Field ll) (Field rr)) :^: M0) l r--instance (ZipMatchFields t1, ZipMatchFields t2, ZipMatchK k) => ZipMatchFields ((Kon k :@: t1) :@: t2) where- type ReqsZipMatchFieldsWith ((Kon k :@: t1) :@: t2) as bs cs = (ReqsZipMatchFieldsWith t1 as bs cs, ReqsZipMatchFieldsWith t2 as bs cs)-- zipMatchFieldsWith :: forall as bs cs. ReqsZipMatchFieldsWith ((Kon k :@: t1) :@: t2) as bs cs =>- Mappings as bs cs -> Field ((Kon k :@: t1) :@: t2) as -> Field ((Kon k :@: t1) :@: t2) bs -> Maybe (Field ((Kon k :@: t1) :@: t2) cs)- zipMatchFieldsWith g (Field l) (Field r) =- Field <$> zipMatchWithK @_ @k @(Interpret t1 as :&&: Interpret t2 as :&&: LoT0) @(Interpret t1 bs :&&: Interpret t2 bs :&&: LoT0) @(Interpret t1 cs :&&: Interpret t2 cs :&&: LoT0)- ((\ll rr -> unField @t1 <$> zipMatchFieldsWith g (Field ll) (Field rr))- :^: ((\ll rr -> unField @t2 <$> zipMatchFieldsWith g (Field ll) (Field rr))- :^: M0)) l r--instance {-# OVERLAPPABLE #-} TypeError ('Text "Atom :@: is not supported by ZipMatchFields is a general form") => ZipMatchFields (f :@: t) where- -- type ReqsZipMatchFieldsWith (f :@: t) as bs cs = TypeError ('Text "Atom :@: is not supported by ZipMatchFields is a general form")- zipMatchFieldsWith = undefined--instance TypeError ('Text "Atom ForAll is not supported by ZipMatchFields") => ZipMatchFields (ForAll a) where- type ReqsZipMatchFieldsWith (ForAll a) as bs cs = TypeError ('Text "Atom ForAll is not supported by ZipMatchFields")- zipMatchFieldsWith = undefined-instance TypeError ('Text "Atom :=>>: is not supported by ZipMatchFields") => ZipMatchFields (c :=>>: a) where- type ReqsZipMatchFieldsWith (c :=>>: a) as bs cs = TypeError ('Text "Atom :=>>: is not supported by ZipMatchFields")- zipMatchFieldsWith = undefined-instance TypeError ('Text "Atom Eval is not supported by ZipMatchFields") => ZipMatchFields (Eval a) where- type ReqsZipMatchFieldsWith (Eval a) as bs cs = TypeError ('Text "Atom Eval is not supported by ZipMatchFields")- zipMatchFieldsWith = undefined---- instance ZipMatchFields (ForAll f) where--- type ReqsZipMatchFields (ForAll f) as bs = ???--- zipMatchFields = ???---- instance ZipMatchFields (c :=>>: f) where--- type ReqsZipMatchFields (c :=>>: f) as bs = ???--- zipMatchFields = ???---- instance ZipMatchFields (Eval f) where--- type ReqsZipMatchFields (Eval f) as bs = ???--- zipMatchFields = ???
src/Control/Monad/Free/Foil/TH.hs view
@@ -2,10 +2,8 @@ module Control.Monad.Free.Foil.TH.Signature, module Control.Monad.Free.Foil.TH.PatternSynonyms, module Control.Monad.Free.Foil.TH.Convert,- module Control.Monad.Free.Foil.TH.ZipMatch, ) where import Control.Monad.Free.Foil.TH.Signature import Control.Monad.Free.Foil.TH.PatternSynonyms import Control.Monad.Free.Foil.TH.Convert-import Control.Monad.Free.Foil.TH.ZipMatch
src/Control/Monad/Free/Foil/TH/PatternSynonyms.hs view
@@ -83,7 +83,7 @@ where l = mkName ("l" ++ show i) - mkPatternName conName = mkName (dropEnd (length "Sig") (nameBase conName))+ mkPatternName conName = mkName (dropEnd (length ("Sig" :: String)) (nameBase conName)) dropEnd k = reverse . drop k . reverse collapse = \case
− src/Control/Monad/Free/Foil/TH/ZipMatch.hs
@@ -1,57 +0,0 @@-{-# OPTIONS_GHC -fno-warn-type-defaults #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE ViewPatterns #-}-module Control.Monad.Free.Foil.TH.ZipMatch where--import Language.Haskell.TH--import Control.Monad.Foil.TH.Util-import Control.Monad.Free.Foil---- | Generate 'ZipMatch' instance for a given bifunctor.-deriveZipMatch- :: Name -- ^ Type name for the signature bifunctor.- -> Q [Dec]-deriveZipMatch signatureT = do- TyConI (DataD _ctx _name signatureTVars _kind signatureCons _deriv) <- reify signatureT-- case reverse signatureTVars of- (tvarName -> term) : (tvarName -> scope) : (reverse -> params) -> do- let signatureType = PeelConT signatureT (map (VarT . tvarName) params)- clauses <- concat <$> mapM (toClause scope term) signatureCons- let defaultClause = Clause [WildP, WildP] (NormalB (ConE 'Nothing)) []- let instType = AppT (ConT ''ZipMatch) signatureType-- return- [ InstanceD Nothing [] instType- [ FunD 'zipMatch (clauses ++ [defaultClause]) ]- ]- _ -> fail "cannot generate pattern synonyms"-- where- toClause :: Name -> Name -> Con -> Q [Clause]- toClause scope term = go- where- go = \case- NormalC conName types -> mkClause conName types- RecC conName types -> go (NormalC conName (map removeName types))- InfixC l conName r -> go (NormalC conName [l, r])- ForallC _ _ con -> go con- GadtC conNames types _retType -> concat <$> mapM (\conName -> mkClause conName types) conNames- RecGadtC conNames types retType -> go (GadtC conNames (map removeName types) retType)-- mkClause :: Name -> [BangType] -> Q [Clause]- mkClause conName types = return- [Clause [ConP conName [] lpats, ConP conName [] rpats]- (NormalB (AppE (ConE 'Just) (foldl AppE (ConE conName) args))) []]- where- (lpats, rpats, args) = unzip3- [ case type_ of- VarT typeName- | typeName `elem` [scope, term] -> (VarP l, VarP r, TupE [Just (VarE l), Just (VarE r)])- _ -> (VarP l, WildP, VarE l)- | (i, (_bang, type_)) <- zip [0..] types- , let l = mkName ("l" ++ show i)- , let r = mkName ("r" ++ show i)- ]
+ src/Data/ZipMatchK.hs view
@@ -0,0 +1,80 @@+{-# OPTIONS_GHC -Wno-redundant-constraints #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+-- | Kind-polymorphic syntactic (first-order) unification.+module Data.ZipMatchK (+ module Data.ZipMatchK.Mappings,+ ZipMatchK(..),+ zipMatchK,+ -- * Specializations+ -- ** Unification of plain 'Data.Kind.Type's+ zipMatchViaEq,+ zipMatchViaChooseLeft,+ -- ** Unification of 'Data.Functor.Functor's+ zipMatchWith1,+ zipMatch1,+ -- ** Unification of 'Data.Bifunctor.Bifunctor's+ zipMatchWith2,+ zipMatch2,+) where++import Generics.Kind+import Data.Bitraversable++import Data.ZipMatchK.Generic+import Data.ZipMatchK.Mappings++-- | Perform one level of equality testing for two values and pair up components using @(,)@:+--+-- > zipMatchK = zipMatchWithK (\x y -> Just (,) :^: M0)+zipMatchK :: forall f as bs. (ZipMatchK f, PairMappings as bs) => f :@@: as -> f :@@: bs -> Maybe (f :@@: ZipLoT as bs)+zipMatchK = zipMatchWithK @_ @f @as @bs pairMappings++-- | Unify values via 'Eq'.+-- Can be used as an implementation of 'zipMatchWithK' when @k = 'Data.Kind.Type'@.+zipMatchViaEq :: Eq a => Mappings as bs cs -> a -> a -> Maybe a+zipMatchViaEq _ x y+ | x == y = Just x+ | otherwise = Nothing++-- | Always successfully unify any two values of type @a@ by preferring the left value.+-- Can be used as an implementation of 'zipMatchWithK' when @k = 'Data.Kind.Type'@.+zipMatchViaChooseLeft :: Mappings as bs cs -> a -> a -> Maybe a+zipMatchViaChooseLeft _ x _ = Just x++-- | 'zipMatchWithK' specialised to functors.+--+-- Note: 'Traversable' is a morally correct constraint here.+zipMatchWith1+ :: (Traversable f, ZipMatchK f)+ => (a -> a' -> Maybe a'')+ -> f a -> f a' -> Maybe (f a'')+zipMatchWith1 f = zipMatchWithK (f :^: M0)++-- | 'zipMatchK' specialised to functors.+--+-- Note: 'Traversable' is a morally correct constraint here.+zipMatch1 :: (Traversable f, ZipMatchK f) => f a -> f a' -> Maybe (f (a, a'))+zipMatch1 = zipMatchWith1 pairA+-- | 'zipMatchWithK' specialised to bifunctors.+--+-- Note: 'Bitraversable' is a morally correct constraint here.+zipMatchWith2+ :: (Bitraversable f, ZipMatchK f)+ => (a -> a' -> Maybe a'')+ -> (b -> b' -> Maybe b'')+ -> f a b -> f a' b' -> Maybe (f a'' b'')+zipMatchWith2 f g = zipMatchWithK (f :^: g :^: M0)++-- | 'zipMatchK' specialised to bifunctors.+--+-- Note: 'Bitraversable' is a morally correct constraint here.+zipMatch2 :: (Bitraversable f, ZipMatchK f) => f a b -> f a' b' -> Maybe (f (a, a') (b, b'))+zipMatch2 = zipMatchWith2 pairA pairA
+ src/Data/ZipMatchK/Bifunctor.hs view
@@ -0,0 +1,35 @@+{-# OPTIONS_GHC -Wno-orphans #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+-- | This module provides 'GenericK' and 'ZipMatchK' instances for 'Sum' and 'Product',+-- to enable the use of 'ZipMatchK' with the data types à la carte approach.+module Data.ZipMatchK.Bifunctor where++import Data.Kind (Type)+import Generics.Kind+import Data.Bitraversable+import Data.Bifunctor.Sum+import Data.Bifunctor.Product++import Data.ZipMatchK++instance GenericK (Sum f g) where+ type RepK (Sum f g) =+ Field ((Kon f :@: Var0) :@: Var1)+ :+: Field ((Kon g :@: Var0) :@: Var1)+instance GenericK (Product f g) where+ type RepK (Product f g) =+ Field ((Kon f :@: Var0) :@: Var1)+ :*: Field ((Kon g :@: Var0) :@: Var1)++-- | Note: instance is limited to 'Type'-kinded bifunctors @f@ and @g@.+instance (Bitraversable f, Bitraversable g, ZipMatchK f, ZipMatchK g) => ZipMatchK (Sum f (g :: Type -> Type -> Type))+-- | Note: instance is limited to 'Type'-kinded bifunctors @f@ and @g@.+instance (Bitraversable f, Bitraversable g, ZipMatchK f, ZipMatchK g) => ZipMatchK (Product f (g :: Type -> Type -> Type))
+ src/Data/ZipMatchK/Functor.hs view
@@ -0,0 +1,34 @@+{-# OPTIONS_GHC -Wno-orphans #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+-- | This module provides 'GenericK' and 'ZipMatchK' instances for 'Sum' and 'Product',+-- to enable the use of 'ZipMatchK' with the data types à la carte approach.+module Data.ZipMatchK.Functor where++import Data.Kind (Type)+import Generics.Kind+import Data.Functor.Sum+import Data.Functor.Product++import Data.ZipMatchK++instance GenericK (Sum f g) where+ type RepK (Sum f g) =+ Field (Kon f :@: Var0)+ :+: Field (Kon g :@: Var0)+instance GenericK (Product f g) where+ type RepK (Product f g) =+ Field (Kon f :@: Var0)+ :*: Field (Kon g :@: Var0)++-- | Note: instance is limited to 'Type'-kinded bifunctors @f@ and @g@.+instance (Traversable f, Traversable g, ZipMatchK f, ZipMatchK g) => ZipMatchK (Sum f (g :: Type -> Type))+-- | Note: instance is limited to 'Type'-kinded bifunctors @f@ and @g@.+instance (Traversable f, Traversable g, ZipMatchK f, ZipMatchK g) => ZipMatchK (Product f (g :: Type -> Type))
+ src/Data/ZipMatchK/Generic.hs view
@@ -0,0 +1,193 @@+{-# OPTIONS_GHC -Wno-missing-methods -Wno-orphans #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneKindSignatures #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+module Data.ZipMatchK.Generic where++import Data.Kind (Constraint, Type)+import Data.List.NonEmpty+import Generics.Kind+import Generics.Kind.Examples ()+import GHC.TypeError+import Data.ZipMatchK.Mappings++-- | Kind-polymorphic syntactic (first-order) unification of two values.+--+-- Note: @f@ is expected to be a traversable n-functor,+-- but at the moment we lack a @TraversableK@ constraint.+class ZipMatchK (f :: k) where+ -- | Perform one level of equality testing:+ --+ -- * when @k = 'Type'@, values are compared directly (e.g. via 'Eq');+ -- * when @k = 'Type' -> 'Type'@, we compare term constructors;+ -- if term constructors are unequal, we return 'Nothing';+ -- otherwise, we pair up all components with a given function.+ zipMatchWithK :: forall as bs cs. Mappings as bs cs -> f :@@: as -> f :@@: bs -> Maybe (f :@@: cs)+ default zipMatchWithK :: forall as bs cs.+ (GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs)+ => Mappings as bs cs -> f :@@: as -> f :@@: bs -> Maybe (f :@@: cs)+ zipMatchWithK = genericZipMatchWithK @f @as @bs @cs++-- | Generic implementation of 'Data.ZipMatch.zipMatchK'.+genericZipMatchK :: forall f as bs.+ (GenericK f, GZipMatch (RepK f), ReqsZipMatch (RepK f) as bs, PairMappings as bs)+ => f :@@: as -> f :@@: bs -> Maybe (f :@@: (ZipLoT as bs))+genericZipMatchK = genericZipMatchWithK @f @as @bs pairMappings++-- | Generic implementation of 'zipMatchWithK'.+genericZipMatchWithK :: forall f as bs cs.+ (GenericK f, GZipMatch (RepK f), ReqsZipMatchWith (RepK f) as bs cs)+ => Mappings as bs cs -> f :@@: as -> f :@@: bs -> Maybe (f :@@: cs)+genericZipMatchWithK mappings x y = toK @_ @f @cs <$> gzipMatchWith mappings+ (fromK @_ @f @as x)+ (fromK @_ @f @bs y)++instance GenericK (,) where+ type RepK (,) = Field Var0 :*: Field Var1+instance GenericK ((,) a) where+ type RepK ((,) a) = Field (Kon a) :*: Field Var0+instance GenericK NonEmpty where+ type RepK NonEmpty = Field Var0 :*: Field ([] :$: Var0)++instance ZipMatchK (,)+instance ZipMatchK a => ZipMatchK ((,) a)+instance ZipMatchK []+instance ZipMatchK Maybe+instance ZipMatchK Either+instance ZipMatchK a => ZipMatchK (Either a)+instance ZipMatchK NonEmpty++type ReqsZipMatch f as bs = ReqsZipMatchWith f as bs (ZipLoT as bs)+class GZipMatch (f :: LoT k -> Type) where+ type ReqsZipMatchWith f (as :: LoT k) (bs :: LoT k) (cs :: LoT k) :: Constraint+ gzipMatchWith :: ReqsZipMatchWith f as bs cs => Mappings as bs cs -> f as -> f bs -> Maybe (f cs)++instance GZipMatch V1 where+ type ReqsZipMatchWith V1 as bs cs = ()+ gzipMatchWith _ _ _ = error "impossible: Generics.Kind.V1 value!" -- FIXME: should be absurd++instance GZipMatch U1 where+ type ReqsZipMatchWith U1 as bs cs = ()+ gzipMatchWith _ U1 U1 = Just U1++instance GZipMatch f => GZipMatch (M1 i c f) where+ type ReqsZipMatchWith (M1 i c f) as bs cs = ReqsZipMatchWith f as bs cs+ gzipMatchWith g (M1 x) (M1 y) = M1 <$> gzipMatchWith g x y++instance (GZipMatch f, GZipMatch g) => GZipMatch (f :+: g) where+ type ReqsZipMatchWith (f :+: g) as bs cs = (ReqsZipMatchWith f as bs cs, ReqsZipMatchWith g as bs cs)+ gzipMatchWith g (L1 x) (L1 y) = L1 <$> gzipMatchWith g x y+ gzipMatchWith g (R1 x) (R1 y) = R1 <$> gzipMatchWith g x y+ gzipMatchWith _ _ _ = Nothing++instance (GZipMatch f, GZipMatch g) => GZipMatch (f :*: g) where+ type ReqsZipMatchWith (f :*: g) as bs cs = (ReqsZipMatchWith f as bs cs, ReqsZipMatchWith g as bs cs)+ gzipMatchWith g (x :*: y) (x' :*: y') =+ liftA2 (:*:) (gzipMatchWith g x x') (gzipMatchWith g y y')++instance ZipMatchFields t => GZipMatch (Field t) where+ type ReqsZipMatchWith (Field t) as bs cs = ReqsZipMatchFieldsWith t as bs cs+ gzipMatchWith f x y = zipMatchFieldsWith f x y++instance GZipMatch f => GZipMatch (c :=>: f) where+ type ReqsZipMatchWith (c :=>: f) as bs cs = (ReqsZipMatchWith f as bs cs, Interpret c cs)+ -- really we want = (Interpret c as, Interpret c bs) => (ReqsZipMatch f as bs, Interpret c (ZipLoT as bs))+ gzipMatchWith g (SuchThat x) (SuchThat y) = SuchThat <$> gzipMatchWith g x y++instance TypeError ('Text "Existentials are not supported")+ => GZipMatch (Exists k f) where+ type ReqsZipMatchWith (Exists k f) as bs cs = TypeError ('Text "Existentials are not supported")+ gzipMatchWith = undefined++class ZipMatchFields (t :: Atom d Type) where+ type ReqsZipMatchFieldsWith t (as :: LoT d) (bs :: LoT d) (cs :: LoT d) :: Constraint+ zipMatchFieldsWith :: ReqsZipMatchFieldsWith t as bs cs => Mappings as bs cs -> Field t as -> Field t bs -> Maybe (Field t cs)++instance ApplyMappings v => ZipMatchFields (Var v) where+ -- this is always true, but GHC is not smart enough to know that, I think+ type ReqsZipMatchFieldsWith (Var v) as bs cs = () -- InterpretVar v cs ~ (InterpretVar v as, InterpretVar v bs))+ zipMatchFieldsWith g (Field x) (Field y) = Field <$> applyMappings @_ @v g x y++instance ZipMatchK k => ZipMatchFields (Kon k) where+ type ReqsZipMatchFieldsWith (Kon k) as bs cs = ()+ zipMatchFieldsWith _ (Field l) (Field r) = Field <$> zipMatchWithK @_ @k M0 l r++instance {-# OVERLAPPING #-} (ZipMatchFields t, ZipMatchK k) => ZipMatchFields (Kon k :@: t) where+ type ReqsZipMatchFieldsWith (Kon k :@: t) as bs cs = ReqsZipMatchFieldsWith t as bs cs++ zipMatchFieldsWith :: forall as bs cs. ReqsZipMatchFieldsWith (Kon k :@: t) as bs cs =>+ Mappings as bs cs -> Field (Kon k :@: t) as -> Field (Kon k :@: t) bs -> Maybe (Field (Kon (k :: Type -> Type) :@: t) cs)+ zipMatchFieldsWith g (Field l) (Field r) =+ Field <$> zipMatchWithK @_ @k @(Interpret t as :&&: LoT0) @(Interpret t bs :&&: LoT0) @(Interpret t cs :&&: LoT0)+ ((\ll rr -> unField @t <$> zipMatchFieldsWith g (Field ll) (Field rr)) :^: M0) l r++instance {-# OVERLAPPING #-} (ZipMatchFields t1, ZipMatchFields t2, ZipMatchK k) => ZipMatchFields ((Kon (k :: Type -> Type -> Type) :@: t1) :@: t2) where+ type ReqsZipMatchFieldsWith ((Kon k :@: t1) :@: t2) as bs cs = (ReqsZipMatchFieldsWith t1 as bs cs, ReqsZipMatchFieldsWith t2 as bs cs)++ zipMatchFieldsWith :: forall as bs cs. ReqsZipMatchFieldsWith ((Kon k :@: t1) :@: t2) as bs cs =>+ Mappings as bs cs -> Field ((Kon k :@: t1) :@: t2) as -> Field ((Kon k :@: t1) :@: t2) bs -> Maybe (Field ((Kon k :@: t1) :@: t2) cs)+ zipMatchFieldsWith g (Field l) (Field r) =+ Field <$> zipMatchWithK @_ @k @(Interpret t1 as :&&: Interpret t2 as :&&: LoT0) @(Interpret t1 bs :&&: Interpret t2 bs :&&: LoT0) @(Interpret t1 cs :&&: Interpret t2 cs :&&: LoT0)+ ((\ll rr -> unField @t1 <$> zipMatchFieldsWith g (Field ll) (Field rr))+ :^: ((\ll rr -> unField @t2 <$> zipMatchFieldsWith g (Field ll) (Field rr))+ :^: M0)) l r++instance {-# OVERLAPPABLE #-} TypeError+ ('Text "The type constructor is kind-polymorphic:"+ :$$: 'Text " " :<>: 'ShowType k :<>: 'Text " : " :<>: 'ShowType (kk -> Type)+ :$$: 'Text "Possible fix:"+ :$$: 'Text " add an explicit kind signature"+ :$$: 'Text " " :<>: 'ShowType k :<>: 'Text " : " :<>: 'ShowType (Type -> Type))+ => ZipMatchFields (Kon (k :: kk -> Type) :@: t) where+ zipMatchFieldsWith = undefined++instance {-# OVERLAPPABLE #-} TypeError+ ('Text "The type constructor is kind-polymorphic:"+ :$$: 'Text " " :<>: 'ShowType k :<>: 'Text " : " :<>: 'ShowType (kk1 -> kk2 -> Type)+ :$$: 'Text "Possible fix:"+ :$$: 'Text " add an explicit kind signature"+ :$$: 'Text " " :<>: 'ShowType k :<>: 'Text " : " :<>: 'ShowType (Type -> Type -> Type))+ => ZipMatchFields ((Kon (k :: kk1 -> kk2 -> Type) :@: t1) :@: t2) where+ zipMatchFieldsWith = undefined++instance {-# OVERLAPPABLE #-} TypeError+ ('Text "Atom :@: is not supported by ZipMatchFields is a general form:"+ :$$: 'Text " when attempting to use a generic instance for"+ :$$: 'ShowType (f :@: t)+ :$$: 'ShowType f :<>: 'Text " : " :<>: 'ShowType (Atom d (k1 -> Type)))+ => ZipMatchFields ((f :: Atom d (k1 -> Type)) :@: t) where+ -- type ReqsZipMatchFieldsWith (f :@: t) as bs cs = TypeError ('Text "Atom :@: is not supported by ZipMatchFields is a general form")+ zipMatchFieldsWith = undefined++instance TypeError+ ('Text "Atom ForAll is not supported by ZipMatchFields"+ :$$: 'Text " when attempting to use a generic instance for"+ :$$: 'ShowType (ForAll a)) => ZipMatchFields (ForAll a) where+ type ReqsZipMatchFieldsWith (ForAll a) as bs cs = TypeError ('Text "Atom ForAll is not supported by ZipMatchFields")+ zipMatchFieldsWith = undefined+instance TypeError+ ('Text "Atom :=>>: is not supported by ZipMatchFields"+ :$$: 'Text " when attempting to use a generic instance for"+ :$$: 'ShowType (c :=>>: a)) => ZipMatchFields (c :=>>: a) where+ type ReqsZipMatchFieldsWith (c :=>>: a) as bs cs = TypeError ('Text "Atom :=>>: is not supported by ZipMatchFields")+ zipMatchFieldsWith = undefined+instance TypeError+ ('Text "Atom Eval is not supported by ZipMatchFields"+ :$$: 'Text " when attempting to use a generic instance for"+ :$$: 'ShowType (Eval a)) => ZipMatchFields (Eval a) where+ type ReqsZipMatchFieldsWith (Eval a) as bs cs = TypeError ('Text "Atom Eval is not supported by ZipMatchFields")+ zipMatchFieldsWith = undefined
+ src/Data/ZipMatchK/Mappings.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE StandaloneKindSignatures #-}+module Data.ZipMatchK.Mappings where++import Data.Kind (Type)+import Generics.Kind++-- | Zip to lists of types into a single list of pair types.+type ZipLoT :: LoT k -> LoT k -> LoT k+type family ZipLoT as bs where+ ZipLoT LoT0 LoT0 = LoT0+ ZipLoT (a :&&: as) (b :&&: bs) = ((a, b) :&&: ZipLoT as bs)++infixr 5 :^:+type Mappings :: LoT k -> LoT k -> LoT k -> Type+-- | A collection of zipping functions for 'Data.ZipMatchK.zipMatchWithK'.+data Mappings (as :: LoT k) (bs :: LoT k) (cs :: LoT k) where+ -- | An empty collection (when there no (more) type parameters).+ M0 :: Mappings LoT0 LoT0 LoT0+ -- | A non-empty collection (when there is at least one type parameter).+ (:^:) :: (a -> b -> Maybe c) -- ^ Zipping for the first type parameter.+ -> Mappings as bs cs -- ^ Zipping for other type parameters.+ -> Mappings (a :&&: as) (b :&&: bs) (c :&&: cs)++class PairMappings (as :: LoT k) (bs :: LoT k) where+ -- | A collection of pairing functions @(\\x y -> Just (x, y))@ for 'Data.ZipMatchK.zipMatchK'.+ pairMappings :: Mappings as bs (ZipLoT as bs)++instance PairMappings LoT0 LoT0 where+ pairMappings = M0++instance PairMappings as bs => PairMappings ((a :: Type) :&&: as) ((b :: Type) :&&: bs) where+ pairMappings = pairA :^: pairMappings++class ApplyMappings (v :: TyVar d Type) where+ -- | Apply a collection of zipping functions to collections of values.+ applyMappings :: forall (as :: LoT d) (bs :: LoT d) (cs :: LoT d).+ Mappings as bs cs -- ^ A collection of zipping functions.+ -> Interpret (Var v) as -- ^ First collection of values (one per type parameter).+ -> Interpret (Var v) bs -- ^ Second collection of values (one per type parameter).+ -> Maybe (Interpret (Var v) cs)++instance ApplyMappings (VZ :: TyVar (Type -> tys) Type) where+ applyMappings (f :^: _) x y = f x y++instance ApplyMappings v => ApplyMappings (VS v :: TyVar (ty -> tys) Type) where+ applyMappings (_ :^: fs) x y = applyMappings @_ @v fs x y++-- | Pair two values in a context.+pairA :: Applicative f => a -> b -> f (a, b)+pairA x y = pure (x, y)