simplistic-generics 0.1.0.0 → 2.0.0
raw patch · 11 files changed
+1870/−227 lines, 11 filesdep +containersdep +deepseqdep +mtldep −comonadPVP ok
version bump matches the API change (PVP)
Dependencies added: containers, deepseq, mtl, template-haskell
Dependencies removed: comonad
API changes (from Hackage documentation)
- Data.Constraints: class (c => d) => Implies c d
- Data.Constraints: class Trivial c
- Data.Constraints: instance (c => d) => Data.Constraints.Implies c d
- Data.Constraints: instance forall k (c :: k). Data.Constraints.Trivial c
- Generics.Simplistic: class Generic1 (f :: k -> Type)
- Generics.Simplistic: data (:=>:) c (f :: k -> Type) (a :: k) :: forall k. () => Constraint -> k -> Type -> k -> Type
- Generics.Simplistic: data M1 i (c :: Meta) (f :: k -> Type) (p :: k) :: forall k. () => Type -> Meta -> k -> Type -> k -> Type
- Generics.Simplistic: data (:*:) (f :: k -> Type) (g :: k -> Type) (p :: k) :: forall k. () => k -> Type -> k -> Type -> k -> Type
- Generics.Simplistic: fromI :: GenericSy a => a -> SRep Identity (Rep a)
- Generics.Simplistic: instance (GHC.Base.Functor f, Generics.Simplistic.Sy1 g) => Generics.Simplistic.Sy1 (f GHC.Generics.:.: g)
- Generics.Simplistic: instance (Generics.Simplistic.SMety i t, Generics.Simplistic.Sy1 f) => Generics.Simplistic.Sy1 (GHC.Generics.M1 i t f)
- Generics.Simplistic: instance (Generics.Simplistic.Sy1 f, Generics.Simplistic.Sy1 g) => Generics.Simplistic.Sy1 (f GHC.Generics.:*: g)
- Generics.Simplistic: instance (Generics.Simplistic.Sy1 f, Generics.Simplistic.Sy1 g) => Generics.Simplistic.Sy1 (f GHC.Generics.:+: g)
- Generics.Simplistic: instance (c => Generics.Simplistic.Sy1 f) => Generics.Simplistic.Sy1 (c GHC.Generics.Extra.:=>: f)
- Generics.Simplistic: instance Generics.Simplistic.Sy (GHC.Generics.K1 i a)
- Generics.Simplistic: instance Generics.Simplistic.Sy GHC.Generics.U1
- Generics.Simplistic: instance Generics.Simplistic.Sy GHC.Generics.V1
- Generics.Simplistic: instance Generics.Simplistic.Sy1 (GHC.Generics.K1 i a)
- Generics.Simplistic: instance Generics.Simplistic.Sy1 (GHC.Generics.Rec1 f)
- Generics.Simplistic: instance Generics.Simplistic.Sy1 GHC.Generics.Par1
- Generics.Simplistic: instance Generics.Simplistic.Sy1 GHC.Generics.U1
- Generics.Simplistic: instance Generics.Simplistic.Sy1 GHC.Generics.V1
- Generics.Simplistic: instance forall k (c :: GHC.Types.Constraint) (f :: k -> *). (c => Generics.Simplistic.Sy f) => Generics.Simplistic.Sy (c GHC.Generics.Extra.:=>: f)
- Generics.Simplistic: instance forall k (c :: k). GHC.Generics.Constructor c => Generics.Simplistic.SMety GHC.Generics.C c
- Generics.Simplistic: instance forall k (d :: k). GHC.Generics.Datatype d => Generics.Simplistic.SMety GHC.Generics.D d
- Generics.Simplistic: instance forall k (f :: k -> *) (g :: k -> *). (Generics.Simplistic.Sy f, Generics.Simplistic.Sy g) => Generics.Simplistic.Sy (f GHC.Generics.:*: g)
- Generics.Simplistic: instance forall k (f :: k -> *) (g :: k -> *). (Generics.Simplistic.Sy f, Generics.Simplistic.Sy g) => Generics.Simplistic.Sy (f GHC.Generics.:+: g)
- Generics.Simplistic: instance forall k (s :: k). GHC.Generics.Selector s => Generics.Simplistic.SMety GHC.Generics.S s
- Generics.Simplistic: instance forall k i (t :: GHC.Generics.Meta) (f :: k -> *). (Generics.Simplistic.SMety i t, Generics.Simplistic.Sy f) => Generics.Simplistic.Sy (GHC.Generics.M1 i t f)
- Generics.Simplistic: toI :: GenericSy a => SRep Identity (Rep a) -> a
- Generics.Simplistic: type GenericSy a = (Generic a, Sy (Rep a))
- Generics.Simplistic: type GenericSy1 f = (Generic1 f, Sy1 (Rep1 f))
- Generics.Simplistic.Derive.Show: Inf :: String -> Type
- Generics.Simplistic.Derive.Show: MyCons :: a -> MyList a -> MyList a
- Generics.Simplistic.Derive.Show: MyNil :: MyList a
- Generics.Simplistic.Derive.Show: Pref :: Type
- Generics.Simplistic.Derive.Show: Rec :: Type
- Generics.Simplistic.Derive.Show: Tup :: Type
- Generics.Simplistic.Derive.Show: [hd] :: MyList a -> a
- Generics.Simplistic.Derive.Show: [tl] :: MyList a -> MyList a
- Generics.Simplistic.Derive.Show: appPrec :: Int
- Generics.Simplistic.Derive.Show: data MyList a
- Generics.Simplistic.Derive.Show: data Type
- Generics.Simplistic.Derive.Show: gshowsPrec' :: OnLeaves Show f => Type -> Int -> SRep Identity f -> ShowS
- Generics.Simplistic.Derive.Show: instance GHC.Generics.Generic (Generics.Simplistic.Derive.Show.MyList a)
- Generics.Simplistic.Derive.Show: instance GHC.Show.Show a => GHC.Show.Show (Generics.Simplistic.Derive.Show.MyList a)
- Generics.Simplistic.Derive.Show: isNullary :: SRep Identity a -> Bool
- Generics.Simplistic.Derive.Show: myListValue :: MyList Integer
+ Generics.Simplistic: (:*:) :: f p -> g p -> (:*:) (f :: k -> Type) (g :: k -> Type) (p :: k)
+ Generics.Simplistic: Comp1 :: f (g p) -> (:.:) (f :: k2 -> Type) (g :: k1 -> k2) (p :: k1)
+ Generics.Simplistic: I :: x -> I x
+ Generics.Simplistic: K1 :: c -> K1 i c (p :: k)
+ Generics.Simplistic: L1 :: f p -> (:+:) (f :: k -> Type) (g :: k -> Type) (p :: k)
+ Generics.Simplistic: M1 :: f p -> M1 i (c :: Meta) (f :: k -> Type) (p :: k)
+ Generics.Simplistic: R1 :: g p -> (:+:) (f :: k -> Type) (g :: k -> Type) (p :: k)
+ Generics.Simplistic: SMetaI :: SMetaI d f x
+ Generics.Simplistic: U1 :: U1 (p :: k)
+ Generics.Simplistic: [SuchThat] :: forall k c (f :: k -> Type) (a :: k). c => f a -> (c :=>: f) a
+ Generics.Simplistic: [unComp1] :: (:.:) (f :: k2 -> Type) (g :: k1 -> k2) (p :: k1) -> f (g p)
+ Generics.Simplistic: [unI] :: I x -> x
+ Generics.Simplistic: [unK1] :: K1 i c (p :: k) -> c
+ Generics.Simplistic: [unM1] :: M1 i (c :: Meta) (f :: k -> Type) (p :: k) -> f p
+ Generics.Simplistic: class GMeta i c
+ Generics.Simplistic: class GShallow f
+ Generics.Simplistic: class GShallow1 f
+ Generics.Simplistic: data ( c :=>: (f :: k -> Type) ) (a :: k)
+ Generics.Simplistic: data Par1 p
+ Generics.Simplistic: data R
+ Generics.Simplistic: data Rec1 (f :: k -> Type) (p :: k)
+ Generics.Simplistic: data SMetaI d f x
+ Generics.Simplistic: data U1 (p :: k)
+ Generics.Simplistic: data V1 (p :: k)
+ Generics.Simplistic: getConstructorName :: SMeta C c -> String
+ Generics.Simplistic: getDatatypeName :: SMeta D d -> String
+ Generics.Simplistic: infixr 7 :.:
+ Generics.Simplistic: instance (GHC.Base.Functor f, Generics.Simplistic.GShallow1 g) => Generics.Simplistic.GShallow1 (f GHC.Generics.:.: g)
+ Generics.Simplistic: instance (Generics.Simplistic.GMeta i t, Generics.Simplistic.GShallow1 f) => Generics.Simplistic.GShallow1 (GHC.Generics.M1 i t f)
+ Generics.Simplistic: instance (Generics.Simplistic.GShallow1 f, Generics.Simplistic.GShallow1 g) => Generics.Simplistic.GShallow1 (f GHC.Generics.:*: g)
+ Generics.Simplistic: instance (Generics.Simplistic.GShallow1 f, Generics.Simplistic.GShallow1 g) => Generics.Simplistic.GShallow1 (f GHC.Generics.:+: g)
+ Generics.Simplistic: instance (c => Generics.Simplistic.GShallow1 f) => Generics.Simplistic.GShallow1 (c GHC.Generics.Extra.:=>: f)
+ Generics.Simplistic: instance GHC.Base.Applicative Generics.Simplistic.I
+ Generics.Simplistic: instance GHC.Base.Functor Generics.Simplistic.I
+ Generics.Simplistic: instance GHC.Base.Monad Generics.Simplistic.I
+ Generics.Simplistic: instance GHC.Classes.Eq x => GHC.Classes.Eq (Generics.Simplistic.I x)
+ Generics.Simplistic: instance GHC.Show.Show x => GHC.Show.Show (Generics.Simplistic.I x)
+ Generics.Simplistic: instance Generics.Simplistic.GShallow (GHC.Generics.K1 GHC.Generics.R x)
+ Generics.Simplistic: instance Generics.Simplistic.GShallow GHC.Generics.U1
+ Generics.Simplistic: instance Generics.Simplistic.GShallow1 (GHC.Generics.K1 i a)
+ Generics.Simplistic: instance Generics.Simplistic.GShallow1 (GHC.Generics.Rec1 f)
+ Generics.Simplistic: instance Generics.Simplistic.GShallow1 GHC.Generics.Par1
+ Generics.Simplistic: instance Generics.Simplistic.GShallow1 GHC.Generics.U1
+ Generics.Simplistic: instance Generics.Simplistic.GShallow1 GHC.Generics.V1
+ Generics.Simplistic: instance forall k (c :: k). GHC.Generics.Constructor c => Generics.Simplistic.GMeta GHC.Generics.C c
+ Generics.Simplistic: instance forall k (d :: k). GHC.Generics.Datatype d => Generics.Simplistic.GMeta GHC.Generics.D d
+ Generics.Simplistic: instance forall k (f :: k -> *) (g :: k -> *). (Generics.Simplistic.GShallow f, Generics.Simplistic.GShallow g) => Generics.Simplistic.GShallow (f GHC.Generics.:*: g)
+ Generics.Simplistic: instance forall k (f :: k -> *) (g :: k -> *). (Generics.Simplistic.GShallow f, Generics.Simplistic.GShallow g) => Generics.Simplistic.GShallow (f GHC.Generics.:+: g)
+ Generics.Simplistic: instance forall k (f :: k -> *) i (c :: GHC.Generics.Meta). (Generics.Simplistic.GShallow f, Generics.Simplistic.GMeta i c) => Generics.Simplistic.GShallow (GHC.Generics.M1 i c f)
+ Generics.Simplistic: instance forall k (s :: k). GHC.Generics.Selector s => Generics.Simplistic.GMeta GHC.Generics.S s
+ Generics.Simplistic: instance forall k (w :: * -> *) (f :: k -> *). (forall a. GHC.Classes.Eq (w a)) => GHC.Classes.Eq (Generics.Simplistic.SRep w f)
+ Generics.Simplistic: instance forall k (w :: * -> *) (f :: k -> *). (forall a. GHC.Show.Show (w a)) => GHC.Show.Show (Generics.Simplistic.SRep w f)
+ Generics.Simplistic: instance forall k (w :: * -> *) (f :: k -> *). (forall x. Control.DeepSeq.NFData (w x)) => Control.DeepSeq.NFData (Generics.Simplistic.SRep w f)
+ Generics.Simplistic: instance forall k i (t :: k). GHC.Classes.Eq (Generics.Simplistic.SMeta i t)
+ Generics.Simplistic: instance forall k i (t :: k). GHC.Show.Show (Generics.Simplistic.SMeta i t)
+ Generics.Simplistic: newtype ( (f :: k2 -> Type) :.: (g :: k1 -> k2) ) (p :: k1)
+ Generics.Simplistic: newtype I x
+ Generics.Simplistic: newtype K1 i c (p :: k)
+ Generics.Simplistic: newtype M1 i (c :: Meta) (f :: k -> Type) (p :: k)
+ Generics.Simplistic: repConstructorName :: SRep w f -> String
+ Generics.Simplistic: repDatatypeName :: SRep w f -> String
+ Generics.Simplistic: repLeaves :: (forall x. w x -> r) -> (r -> r -> r) -> r -> SRep w rep -> r
+ Generics.Simplistic: repLeavesC :: OnLeaves c rep => Proxy c -> (forall x. c x => w x -> r) -> (r -> r -> r) -> r -> SRep w rep -> r
+ Generics.Simplistic: repLeavesList :: SRep w rep -> [Exists w]
+ Generics.Simplistic: repMap :: (forall y. f y -> g y) -> SRep f rep -> SRep g rep
+ Generics.Simplistic: repMapCM :: (Monad m, OnLeaves c rep) => Proxy c -> (forall y. c y => f y -> m (g y)) -> SRep f rep -> m (SRep g rep)
+ Generics.Simplistic: repMapM :: Monad m => (forall y. f y -> m (g y)) -> SRep f rep -> m (SRep g rep)
+ Generics.Simplistic: sfrom :: GShallow f => f x -> SRep I f
+ Generics.Simplistic: sfrom1 :: GShallow1 f => f a -> SRep1 f a
+ Generics.Simplistic: smeta :: GMeta i c => SMeta i c
+ Generics.Simplistic: sto :: GShallow f => SRep I f -> f x
+ Generics.Simplistic: sto1 :: GShallow1 f => SRep1 f a -> f a
+ Generics.Simplistic: type Simplistic a = (Generic a, GShallow (Rep a))
+ Generics.Simplistic: type Simplistic1 f = (Generic1 f, GShallow1 (Rep1 f))
+ Generics.Simplistic: zipSRep :: SRep w f -> SRep z f -> Maybe (SRep (w :*: z) f)
+ Generics.Simplistic.Deep: [Hole'] :: ann a -> h a -> HolesAnn kappa fam ann h a
+ Generics.Simplistic.Deep: [Prim'] :: PrimCnstr kappa fam a => ann a -> a -> HolesAnn kappa fam ann h a
+ Generics.Simplistic.Deep: [Roll'] :: CompoundCnstr kappa fam a => ann a -> SRep (HolesAnn kappa fam ann h) (Rep a) -> HolesAnn kappa fam ann h a
+ Generics.Simplistic.Deep: cataM :: Monad m => (forall b. CompoundCnstr kappa fam b => ann b -> SRep phi (Rep b) -> m (phi b)) -> (forall b. PrimCnstr kappa fam b => ann b -> b -> m (phi b)) -> (forall b. ann b -> h b -> m (phi b)) -> HolesAnn kappa fam ann h a -> m (phi a)
+ Generics.Simplistic.Deep: class (CompoundCnstr kappa fam a) => Deep kappa fam a
+ Generics.Simplistic.Deep: class GDeep kappa fam f
+ Generics.Simplistic.Deep: data HolesAnn kappa fam ann h a
+ Generics.Simplistic.Deep: dfrom :: (Deep kappa fam a, GDeep kappa fam (Rep a)) => a -> SFix kappa fam a
+ Generics.Simplistic.Deep: dto :: (Deep kappa fam a, GDeep kappa fam (Rep a)) => SFix kappa fam a -> a
+ Generics.Simplistic.Deep: gdfrom :: GDeep kappa fam f => f x -> SRep (SFix kappa fam) f
+ Generics.Simplistic.Deep: gdto :: GDeep kappa fam f => SRep (SFix kappa fam) f -> f x
+ Generics.Simplistic.Deep: getAnn :: HolesAnn kappa fam ann h a -> ann a
+ Generics.Simplistic.Deep: holesHolesList :: HolesAnn kappa fam ann f a -> [Exists f]
+ Generics.Simplistic.Deep: holesJoin :: HolesAnn kappa fam ann (HolesAnn kappa fam ann f) a -> HolesAnn kappa fam ann f a
+ Generics.Simplistic.Deep: holesMap :: (forall x. f x -> g x) -> HolesAnn kappa fam ann f a -> HolesAnn kappa fam ann g a
+ Generics.Simplistic.Deep: holesMapAnn :: (forall x. f x -> g x) -> (forall x. ann x -> phi x) -> HolesAnn kappa fam ann f a -> HolesAnn kappa fam phi g a
+ Generics.Simplistic.Deep: holesMapAnnM :: Monad m => (forall x. f x -> m (g x)) -> (forall x. ann x -> m (psi x)) -> HolesAnn kappa fam ann f a -> m (HolesAnn kappa fam psi g a)
+ Generics.Simplistic.Deep: holesMapM :: Monad m => (forall x. f x -> m (g x)) -> HolesAnn kappa fam ann f a -> m (HolesAnn kappa fam ann g a)
+ Generics.Simplistic.Deep: holesRefineHoles :: (forall b. f b -> Holes kappa fam g b) -> Holes kappa fam f a -> Holes kappa fam g a
+ Generics.Simplistic.Deep: holesRefineHolesM :: Monad m => (forall b. f b -> m (Holes kappa fam g b)) -> Holes kappa fam f a -> m (Holes kappa fam g a)
+ Generics.Simplistic.Deep: holesRefineM :: Monad m => (forall b. f b -> m (Holes kappa fam g b)) -> (forall b. PrimCnstr kappa fam b => b -> m (Holes kappa fam g b)) -> Holes kappa fam f a -> m (Holes kappa fam g a)
+ Generics.Simplistic.Deep: holesSize :: HolesAnn kappa fam ann h a -> Int
+ Generics.Simplistic.Deep: holesToSFix :: Holes kappa fam V1 at -> SFix kappa fam at
+ Generics.Simplistic.Deep: instance (Generics.Simplistic.Deep.CompoundCnstr kappa fam a, Generics.Simplistic.Deep.Deep kappa fam a) => Generics.Simplistic.Deep.GDeepAtom kappa fam 'GHC.Types.False a
+ Generics.Simplistic.Deep: instance (Generics.Simplistic.Util.All GHC.Classes.Eq kappa, Generics.Simplistic.Util.EqHO h) => GHC.Classes.Eq (Generics.Simplistic.Deep.Holes kappa fam h t)
+ Generics.Simplistic.Deep: instance (Generics.Simplistic.Util.All GHC.Classes.Eq kappa, Generics.Simplistic.Util.EqHO h) => Generics.Simplistic.Util.EqHO (Generics.Simplistic.Deep.Holes kappa fam h)
+ Generics.Simplistic.Deep: instance (forall x. Control.DeepSeq.NFData (ann x), forall x. Control.DeepSeq.NFData (h x)) => Control.DeepSeq.NFData (Generics.Simplistic.Deep.HolesAnn kappa fam ann h f)
+ Generics.Simplistic.Deep: instance Generics.Simplistic.Deep.GDeep kappa fam GHC.Generics.U1
+ Generics.Simplistic.Deep: instance Generics.Simplistic.Deep.GDeepAtom kappa fam (Generics.Simplistic.Util.IsElem a kappa) a => Generics.Simplistic.Deep.GDeep kappa fam (GHC.Generics.K1 GHC.Generics.R a)
+ Generics.Simplistic.Deep: instance Generics.Simplistic.Deep.PrimCnstr kappa fam a => Generics.Simplistic.Deep.GDeepAtom kappa fam 'GHC.Types.True a
+ Generics.Simplistic.Deep: instance forall k (kappa :: [*]) (fam :: [*]) (f :: k -> *) (g :: k -> *). (Generics.Simplistic.Deep.GDeep kappa fam f, Generics.Simplistic.Deep.GDeep kappa fam g) => Generics.Simplistic.Deep.GDeep kappa fam (f GHC.Generics.:*: g)
+ Generics.Simplistic.Deep: instance forall k (kappa :: [*]) (fam :: [*]) (f :: k -> *) (g :: k -> *). (Generics.Simplistic.Deep.GDeep kappa fam f, Generics.Simplistic.Deep.GDeep kappa fam g) => Generics.Simplistic.Deep.GDeep kappa fam (f GHC.Generics.:+: g)
+ Generics.Simplistic.Deep: instance forall k (x :: k). Control.DeepSeq.NFData (GHC.Generics.U1 x)
+ Generics.Simplistic.Deep: instance forall k (x :: k). Control.DeepSeq.NFData (GHC.Generics.V1 x)
+ Generics.Simplistic.Deep: instance forall k i (c :: GHC.Generics.Meta) (kappa :: [*]) (fam :: [*]) (f :: k -> *). (Generics.Simplistic.GMeta i c, Generics.Simplistic.Deep.GDeep kappa fam f) => Generics.Simplistic.Deep.GDeep kappa fam (GHC.Generics.M1 i c f)
+ Generics.Simplistic.Deep: lgg :: forall kappa fam h i a. All Eq kappa => Holes kappa fam h a -> Holes kappa fam i a -> Holes kappa fam (Holes kappa fam h :*: Holes kappa fam i) a
+ Generics.Simplistic.Deep: pattern Hole :: h a -> Holes kappa fam h a
+ Generics.Simplistic.Deep: pattern Roll :: () => CompoundCnstr kappa fam a => SRep (Holes kappa fam h) (Rep a) -> Holes kappa fam h a
+ Generics.Simplistic.Deep: pattern Prim :: () => PrimCnstr kappa fam a => a -> Holes kappa fam h a
+ Generics.Simplistic.Deep: pattern PrimAnn :: () => PrimCnstr kappa fam a => ann a -> a -> SFixAnn kappa fam ann a
+ Generics.Simplistic.Deep: sfixToHoles :: SFix kappa fam at -> Holes kappa fam h at
+ Generics.Simplistic.Deep: synthesize :: (forall b. CompoundCnstr kappa fam b => ann b -> SRep phi (Rep b) -> phi b) -> (forall b. PrimCnstr kappa fam b => ann b -> b -> phi b) -> (forall b. ann b -> h b -> phi b) -> HolesAnn kappa fam ann h a -> HolesAnn kappa fam phi h a
+ Generics.Simplistic.Deep: synthesizeM :: Monad m => (forall b. CompoundCnstr kappa fam b => ann b -> SRep phi (Rep b) -> m (phi b)) -> (forall b. PrimCnstr kappa fam b => ann b -> b -> m (phi b)) -> (forall b. ann b -> h b -> m (phi b)) -> HolesAnn kappa fam ann h a -> m (HolesAnn kappa fam phi h a)
+ Generics.Simplistic.Deep: type CompoundCnstr kappa fam a = (Elem a fam, NotElem a kappa, Generic a)
+ Generics.Simplistic.Deep: type Holes kappa fam = HolesAnn kappa fam U1
+ Generics.Simplistic.Deep: type PrimCnstr kappa fam b = (Elem b kappa, NotElem b fam)
+ Generics.Simplistic.Deep: type SFix kappa fam = HolesAnn kappa fam U1 V1
+ Generics.Simplistic.Deep: type SFixAnn kappa fam ann = HolesAnn kappa fam ann V1
+ Generics.Simplistic.Deep.TH: deriveDeepFor :: Name -> Name -> Q [Dec]
+ Generics.Simplistic.Deep.TH: deriveInstancesWith :: (Type -> Q Type) -> Name -> Q [Dec]
+ Generics.Simplistic.Deep.TH: instance GHC.Classes.Eq Generics.Simplistic.Deep.TH.STy
+ Generics.Simplistic.Deep.TH: instance GHC.Classes.Ord Generics.Simplistic.Deep.TH.STy
+ Generics.Simplistic.Deep.TH: instance GHC.Show.Show Generics.Simplistic.Deep.TH.STy
+ Generics.Simplistic.Deep.TH: unfoldFamilyInto :: String -> Q Type -> Q [Dec]
+ Generics.Simplistic.Unify: [OccursCheck] :: [Exists phi] -> UnifyErr kappa fam phi
+ Generics.Simplistic.Unify: [SymbolClash] :: Holes kappa fam phi at -> Holes kappa fam phi at -> UnifyErr kappa fam phi
+ Generics.Simplistic.Unify: data UnifyErr kappa fam phi :: *
+ Generics.Simplistic.Unify: minimize :: forall kappa fam phi. Ord (Exists phi) => Subst kappa fam phi -> Either [Exists phi] (Subst kappa fam phi)
+ Generics.Simplistic.Unify: substApply :: Ord (Exists phi) => Subst kappa fam phi -> Holes kappa fam phi at -> Holes kappa fam phi at
+ Generics.Simplistic.Unify: substEmpty :: Subst kappa fam phi
+ Generics.Simplistic.Unify: substInsert :: Ord (Exists phi) => Subst kappa fam phi -> phi at -> Holes kappa fam phi at -> Subst kappa fam phi
+ Generics.Simplistic.Unify: substLkup :: Ord (Exists phi) => Subst kappa fam phi -> phi at -> Maybe (Holes kappa fam phi at)
+ Generics.Simplistic.Unify: type Subst kappa fam phi = Map (Exists phi) (Exists (Holes kappa fam phi))
+ Generics.Simplistic.Unify: unify :: (All Eq kappa, Ord (Exists phi), EqHO phi) => Holes kappa fam phi at -> Holes kappa fam phi at -> Except (UnifyErr kappa fam phi) (Subst kappa fam phi)
+ Generics.Simplistic.Unify: unifyWith :: (All Eq kappa, Ord (Exists phi), EqHO phi) => Subst kappa fam phi -> Holes kappa fam phi at -> Holes kappa fam phi at -> Except (UnifyErr kappa fam phi) (Subst kappa fam phi)
+ Generics.Simplistic.Unify: unify_ :: (All Eq kappa, Ord (Exists phi), EqHO phi) => Holes kappa fam phi at -> Holes kappa fam phi at -> Maybe (Subst kappa fam phi)
+ Generics.Simplistic.Util: (&&&) :: Arrow a => a b c -> a b c' -> a b (c, c')
+ Generics.Simplistic.Util: (***) :: Arrow a => a b c -> a b' c' -> a (b, b') (c, c')
+ Generics.Simplistic.Util: (:*:) :: f p -> g p -> (:*:) (f :: k -> Type) (g :: k -> Type) (p :: k)
+ Generics.Simplistic.Util: (<.>) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
+ Generics.Simplistic.Util: InL :: f a -> Sum (f :: k -> Type) (g :: k -> Type) (a :: k)
+ Generics.Simplistic.Util: InR :: g a -> Sum (f :: k -> Type) (g :: k -> Type) (a :: k)
+ Generics.Simplistic.Util: [Exists] :: f x -> Exists f
+ Generics.Simplistic.Util: [Here] :: ElemPrf a (a : as)
+ Generics.Simplistic.Util: [There] :: ElemPrf a as -> ElemPrf a (b : as)
+ Generics.Simplistic.Util: [Witness] :: c x => Witness c x
+ Generics.Simplistic.Util: class EqHO (f :: ki -> *)
+ Generics.Simplistic.Util: class HasElem a as
+ Generics.Simplistic.Util: class (c => d) => Implies c d
+ Generics.Simplistic.Util: class ShowHO (f :: ki -> *)
+ Generics.Simplistic.Util: class Trivial c
+ Generics.Simplistic.Util: curry' :: ((f :*: g) x -> a) -> f x -> g x -> a
+ Generics.Simplistic.Util: data ( (f :: k -> Type) :*: (g :: k -> Type) ) (p :: k)
+ Generics.Simplistic.Util: data ElemPrf a as
+ Generics.Simplistic.Util: data Exists (f :: k -> *) :: *
+ Generics.Simplistic.Util: data Sum (f :: k -> Type) (g :: k -> Type) (a :: k)
+ Generics.Simplistic.Util: data Witness c x
+ Generics.Simplistic.Util: delta :: f :-> Delta f
+ Generics.Simplistic.Util: deltaMap :: (f :-> g) -> Delta f :-> Delta g
+ Generics.Simplistic.Util: either' :: (f :-> r) -> (g :-> r) -> Sum f g :-> r
+ Generics.Simplistic.Util: either'' :: (forall x. f x -> a) -> (forall y. g y -> a) -> Sum f g r -> a
+ Generics.Simplistic.Util: eqHO :: forall k. EqHO f => f k -> f k -> Bool
+ Generics.Simplistic.Util: exElim :: (forall x. f x -> a) -> Exists f -> a
+ Generics.Simplistic.Util: exMap :: (forall x. f x -> g x) -> Exists f -> Exists g
+ Generics.Simplistic.Util: exMapM :: Monad m => (forall x. f x -> m (g x)) -> Exists f -> m (Exists g)
+ Generics.Simplistic.Util: hasElem :: HasElem a as => ElemPrf a as
+ Generics.Simplistic.Util: infixr 3 ***
+ Generics.Simplistic.Util: infixr 6 :*:
+ Generics.Simplistic.Util: infixr 8 <.>
+ Generics.Simplistic.Util: instance (c => d) => Generics.Simplistic.Util.Implies c d
+ Generics.Simplistic.Util: instance GHC.Classes.Eq a => Generics.Simplistic.Util.EqHO (Data.Functor.Const.Const a)
+ Generics.Simplistic.Util: instance GHC.Show.Show a => Generics.Simplistic.Util.ShowHO (Data.Functor.Const.Const a)
+ Generics.Simplistic.Util: instance Generics.Simplistic.Util.EqHO GHC.Generics.U1
+ Generics.Simplistic.Util: instance Generics.Simplistic.Util.EqHO GHC.Generics.V1
+ Generics.Simplistic.Util: instance forall a1 (a2 :: a1) (as :: [a1]) (b :: a1). Generics.Simplistic.Util.HasElem a2 as => Generics.Simplistic.Util.HasElem a2 (b : as)
+ Generics.Simplistic.Util: instance forall a1 (a2 :: a1) (as :: [a1]). Generics.Simplistic.Util.HasElem a2 (a2 : as)
+ Generics.Simplistic.Util: instance forall k (c :: k). Generics.Simplistic.Util.Trivial c
+ Generics.Simplistic.Util: instance forall k (f :: k -> *). Generics.Simplistic.Util.ShowHO f => GHC.Show.Show (Generics.Simplistic.Util.Exists f)
+ Generics.Simplistic.Util: instance forall ki (f :: ki -> *) (g :: ki -> *). (Generics.Simplistic.Util.EqHO f, Generics.Simplistic.Util.EqHO g) => Generics.Simplistic.Util.EqHO (Data.Functor.Sum.Sum f g)
+ Generics.Simplistic.Util: instance forall ki (f :: ki -> *) (g :: ki -> *). (Generics.Simplistic.Util.EqHO f, Generics.Simplistic.Util.EqHO g) => Generics.Simplistic.Util.EqHO (f GHC.Generics.:*: g)
+ Generics.Simplistic.Util: instance forall ki (f :: ki -> *) (g :: ki -> *). (Generics.Simplistic.Util.ShowHO f, Generics.Simplistic.Util.ShowHO g) => Generics.Simplistic.Util.ShowHO (Data.Functor.Sum.Sum f g)
+ Generics.Simplistic.Util: instance forall ki (f :: ki -> *) (g :: ki -> *). (Generics.Simplistic.Util.ShowHO f, Generics.Simplistic.Util.ShowHO g) => Generics.Simplistic.Util.ShowHO (f GHC.Generics.:*: g)
+ Generics.Simplistic.Util: sameTy :: forall fam x y. (Elem x fam, Elem y fam) => Proxy fam -> Proxy x -> Proxy y -> Maybe (x :~: y)
+ Generics.Simplistic.Util: showHO :: forall k. ShowHO f => f k -> String
+ Generics.Simplistic.Util: showsPrecHO :: forall k. ShowHO f => Int -> f k -> ShowS
+ Generics.Simplistic.Util: type Delta f = f :*: f
+ Generics.Simplistic.Util: type Elem a as = (IsElem a as ~ 'True, HasElem a as)
+ Generics.Simplistic.Util: type NotElem a as = IsElem a as ~ 'False
+ Generics.Simplistic.Util: type f :-> g = forall n. f n -> g n
+ Generics.Simplistic.Util: type family All (c :: k -> Constraint) (xs :: [k]) :: Constraint
+ Generics.Simplistic.Util: uncurry' :: (f x -> g x -> a) -> (f :*: g) x -> a
+ Generics.Simplistic.Util: weq :: forall x xs. (All Eq xs, Elem x xs) => Proxy xs -> x -> x -> Bool
+ Generics.Simplistic.Util: witness :: forall x xs c. (HasElem x xs, All c xs) => Proxy xs -> Witness c x
+ Generics.Simplistic.Util: witnessPrf :: All c xs => ElemPrf x xs -> Witness c x
+ Generics.Simplistic.Util: wshow :: forall x xs. (All Show xs, Elem x xs) => Proxy xs -> x -> String
+ Generics.Simplistic.Zipper: [Z_KH] :: SZip ty w (K1 i ty)
+ Generics.Simplistic.Zipper: [Z_L1] :: SZip ty w f -> SZip ty w (f :+: g)
+ Generics.Simplistic.Zipper: [Z_M1] :: SMeta i t -> SZip ty w f -> SZip ty w (M1 i t f)
+ Generics.Simplistic.Zipper: [Z_PairL] :: SZip ty w f -> SRep w g -> SZip ty w (f :*: g)
+ Generics.Simplistic.Zipper: [Z_PairR] :: SRep w f -> SZip ty w g -> SZip ty w (f :*: g)
+ Generics.Simplistic.Zipper: [Z_R1] :: SZip ty w g -> SZip ty w (f :+: g)
+ Generics.Simplistic.Zipper: [Zipper] :: c => {zipper :: SZip t f (Rep t), sel :: g t} -> Zipper c f g t
+ Generics.Simplistic.Zipper: data SZip ty w f
+ Generics.Simplistic.Zipper: data Zipper c f g t
+ Generics.Simplistic.Zipper: inr1 :: (x :*: y) t -> (Sum z x :*: y) t
+ Generics.Simplistic.Zipper: instance forall k (w :: * -> *) h (f :: k -> *). (forall a. GHC.Classes.Eq (w a)) => GHC.Classes.Eq (Generics.Simplistic.Zipper.SZip h w f)
+ Generics.Simplistic.Zipper: instance forall k (w :: * -> *) h (f :: k -> *). (forall a. GHC.Show.Show (w a)) => GHC.Show.Show (Generics.Simplistic.Zipper.SZip h w f)
+ Generics.Simplistic.Zipper: plug :: SZip ty phi f -> phi ty -> SRep phi f
+ Generics.Simplistic.Zipper: type Zipper' kappa fam ann phi t = Zipper (CompoundCnstr kappa fam t) (HolesAnn kappa fam ann phi) (HolesAnn kappa fam ann phi) t
+ Generics.Simplistic.Zipper: zipConstructorName :: SZip h w f -> String
+ Generics.Simplistic.Zipper: zipLeavesList :: SZip ty w f -> [Maybe (Exists w)]
+ Generics.Simplistic.Zipper: zipSZip :: SZip ty h f -> SZip ty w f -> Maybe (SZip ty (h :*: w) f)
+ Generics.Simplistic.Zipper: zipperMap :: (forall x. h x -> g x) -> SZip ty h f -> SZip ty g f
+ Generics.Simplistic.Zipper: zipperRepZip :: SZip ty h f -> SRep w f -> Maybe (SRep (Sum ((:~:) ty) h :*: w) f)
+ Generics.Simplistic.Zipper: zippers :: forall kappa fam ann phi t. (forall a. Elem t fam => phi a -> Maybe (a :~: t)) -> HolesAnn kappa fam ann phi t -> [Zipper' kappa fam ann phi t]
- Generics.Simplistic: fromS :: (GenericSy a, Applicative w) => a -> SRep w (Rep a)
+ Generics.Simplistic: fromS :: Simplistic a => a -> SRep I (Rep a)
- Generics.Simplistic: fromS1 :: GenericSy1 f => f a -> SRep1 (Rep1 f) a
+ Generics.Simplistic: fromS1 :: Simplistic1 f => f x -> SRep1 (Rep1 f) x
- Generics.Simplistic: toS :: (GenericSy a, Comonad w) => SRep w (Rep a) -> a
+ Generics.Simplistic: toS :: Simplistic a => SRep I (Rep a) -> a
- Generics.Simplistic: toS1 :: GenericSy1 f => SRep1 (Rep1 f) a -> f a
+ Generics.Simplistic: toS1 :: Simplistic1 f => SRep1 (Rep1 f) x -> f x
- Generics.Simplistic.Derive.Eq: geq :: (Applicative w, OnLeaves Eq f) => SRep w f -> SRep w f -> w Bool
+ Generics.Simplistic.Derive.Eq: geq :: (Generic a, GShallow (Rep a), OnLeaves Eq (Rep a)) => a -> a -> Bool
- Generics.Simplistic.Derive.Eq: geq' :: (GenericSy a, OnLeaves Eq (Rep a)) => a -> a -> Bool
+ Generics.Simplistic.Derive.Eq: geq' :: OnLeaves Eq f => SRep I f -> SRep I f -> Bool
- Generics.Simplistic.Derive.Functor: gfmap :: OnLeaves1 Trivial Functor f => (a -> b) -> SRep1 f a -> SRep1 f b
+ Generics.Simplistic.Derive.Functor: gfmap :: (Simplistic1 f, OnLeaves1 Trivial Functor (Rep1 f)) => (a -> b) -> f a -> f b
- Generics.Simplistic.Derive.Functor: gfmap' :: (GenericSy1 f, OnLeaves1 Trivial Functor (Rep1 f)) => (a -> b) -> f a -> f b
+ Generics.Simplistic.Derive.Functor: gfmap' :: OnLeaves1 Trivial Functor f => (a -> b) -> SRep1 f a -> SRep1 f b
- Generics.Simplistic.Derive.Show: gshow :: (GenericSy t, OnLeaves Show (Rep t)) => t -> String
+ Generics.Simplistic.Derive.Show: gshow :: (Generic t, GShallow (Rep t), OnLeaves Show (Rep t)) => t -> String
- Generics.Simplistic.Derive.Show: gshowsPrec :: (GenericSy t, OnLeaves Show (Rep t)) => Type -> Int -> t -> ShowS
+ Generics.Simplistic.Derive.Show: gshowsPrec :: (Generic t, GShallow (Rep t), OnLeaves Show (Rep t)) => Type -> Int -> t -> ShowS
Files
- simplistic-generics.cabal +46/−30
- src/Data/Constraints.hs +0/−16
- src/Generics/Simplistic.hs +339/−115
- src/Generics/Simplistic/Deep.hs +390/−0
- src/Generics/Simplistic/Deep/TH.hs +315/−0
- src/Generics/Simplistic/Derive/Eq.hs +16/−18
- src/Generics/Simplistic/Derive/Functor.hs +23/−17
- src/Generics/Simplistic/Derive/Show.hs +30/−31
- src/Generics/Simplistic/Unify.hs +289/−0
- src/Generics/Simplistic/Util.hs +249/−0
- src/Generics/Simplistic/Zipper.hs +173/−0
simplistic-generics.cabal view
@@ -1,33 +1,49 @@-cabal-version: >=1.10-name: simplistic-generics-version: 0.1.0.0-synopsis: Generic programming without too many type classes-description: This library provides a representation build on top of - `GHC.Generics`, which can be used to describe generic- operations on a single function, instead of having- each case defined in an instance of a type class.--- bug-reports:-license: BSD3-license-file: LICENSE-author: Alejandro Serrano-maintainer: trupill@gmail.com--- copyright:-category: Data-build-type: Simple-extra-source-files: README.md+cabal-version: 1.12 -library- exposed-modules: Generics.Simplistic,- Generics.Simplistic.Derive.Eq,- Generics.Simplistic.Derive.Functor,- Generics.Simplistic.Derive.Show- Data.Constraints- -- other-modules:- -- other-extensions:- build-depends: base >=4.12 && <5, kind-apply, comonad- hs-source-dirs: src- default-language: Haskell2010+-- This file has been generated from package.yaml by hpack version 0.31.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: 1b90926eead859c5af167c81f38f7e1fc252fdba35adaaad6ee34ae33b85009b +name: simplistic-generics+version: 2.0.0+synopsis: Generic programming without too many type classes+description: This library provides a representation build on top of `GHC.Generics`, which can be used to describe generic operations on a single function, instead of having each case defined in an instance of a type class.+category: Data+author: Alejandro Serrano and Victor Miraldo+maintainer: trupill@gmail.com and v.cacciarimiraldo@gmail.com+license: BSD3+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md+ source-repository head- type: git- location: https://gitlab.com/trupill/simplistic-generics+ type: git+ location: https://gitlab.com/trupill/simplistic-generics++library+ exposed-modules:+ Generics.Simplistic+ Generics.Simplistic.Deep+ Generics.Simplistic.Deep.TH+ Generics.Simplistic.Derive.Eq+ Generics.Simplistic.Derive.Functor+ Generics.Simplistic.Derive.Show+ Generics.Simplistic.Unify+ Generics.Simplistic.Util+ Generics.Simplistic.Zipper+ other-modules:+ Paths_simplistic_generics+ hs-source-dirs:+ src/+ ghc-options: -O2 -Wall+ build-depends:+ base >=4.12 && <5+ , containers+ , deepseq+ , kind-apply+ , mtl+ , template-haskell+ default-language: Haskell2010
− src/Data/Constraints.hs
@@ -1,16 +0,0 @@-{-# language MultiParamTypeClasses,- UndecidableInstances,- QuantifiedConstraints,- ConstraintKinds,- FlexibleInstances,- KindSignatures,- PolyKinds #-}-module Data.Constraints where--import GHC.Exts (Constraint)--class (c => d) => Implies c d-instance (c => d) => Implies c d--class Trivial c-instance Trivial c
src/Generics/Simplistic.hs view
@@ -1,63 +1,123 @@-{-# language GADTs,- DataKinds,- PolyKinds,- TypeOperators,- ConstraintKinds,- MultiParamTypeClasses,- FlexibleContexts,- FlexibleInstances,- QuantifiedConstraints,- UndecidableInstances,- KindSignatures,- TypeFamilies #-}-module Generics.Simplistic (- -- * From `GHC.Generics.Extra` module- Generic, Rep, Generic1, Rep1,- V1, U1, (:+:), (:*:), K1, M1, (:=>:),- -- * Simplistic representation on `*` types - SMeta(..), SRep(..), GenericSy, fromS, toS, fromI, toI,- -- ** Constraints over the leaves of a data type- OnLeaves,- -- * Simplistic representation on `* -> *` types - SRep1(..), GenericSy1, fromS1, toS1,+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+-- |Introduces closed representations functor+-- for "GHC.Generics" style generics.+module Generics.Simplistic+ ( -- ** Re-exports from "GHC.Generics.Extra" module+ Generic, Rep, Rep1, Par1, Rec1, (:.:)(..), V1, U1(..), (:+:)(..)+ , (:*:)(..), K1(..), M1(..), (:=>:)(..), R+ -- * Simplistic representation on @*@ types+ , GMeta(..), SMeta(..), SMetaI(..), SRep(..) , I(..) , Simplistic -- ** Constraints over the leaves of a data type- OnLeaves1,+ , OnLeaves+ -- ** Combinators+ -- *** Maps , zips and folds+ , repMap , repMapM , repMapCM+ , zipSRep , repLeaves , repLeavesC , repLeavesList+ -- *** Metadata+ , getDatatypeName , getConstructorName+ , repDatatypeName , repConstructorName+ -- ** Shallow Conversion+ , fromS , toS , GShallow(..)+ -- * Simplistic representation on @* -> *@ types+ , SRep1(..) , OnLeaves1 , fromS1 , toS1 , GShallow1(..) , Simplistic1 -- * Auxiliary constraints- Implies, Trivial-) where+ , Implies, Trivial+ ) where -import Control.Comonad-import Data.Functor.Identity-import Data.Constraints+import Data.Proxy+import Control.Monad.Identity+import Control.DeepSeq++import GHC.Generics import GHC.Generics.Extra import GHC.Exts (Constraint) +import Generics.Simplistic.Util ++---------------------+-- Representations --+---------------------+ data SMeta i t where SM_D :: Datatype d => SMeta D d SM_C :: Constructor c => SMeta C c SM_S :: Selector s => SMeta S s+deriving instance Show (SMeta i t)+deriving instance Eq (SMeta i t) +-- Dirty trick to access the dictionaries I need+data SMetaI d f x = SMetaI++smetaI :: SMeta i t -> SMetaI t Proxy ()+smetaI _ = SMetaI++getDatatypeName :: SMeta D d -> String+getDatatypeName x@SM_D = datatypeName (smetaI x)++getConstructorName :: SMeta C c -> String+getConstructorName x@SM_C = conName (smetaI x)++-- |Singletons for metainformation+class GMeta i c where+ smeta :: SMeta i c++instance Constructor c => GMeta C c where+ smeta = SM_C++instance Datatype d => GMeta D d where+ smeta = SM_D++instance Selector s => GMeta S s where+ smeta = SM_S++-- |Given some @a@, a value of type @SRep w (Rep a)@ is+-- a closed representation of a generic value of type @a@. infixr 5 :**: data SRep w f where S_U1 :: SRep w U1 S_L1 :: SRep w f -> SRep w (f :+: g) S_R1 :: SRep w g -> SRep w (f :+: g)- (:**:) :: SRep w f -> SRep w g -> SRep w (f :*: g)+ (:**:) :: SRep w f -> SRep w g -> SRep w (f :*: g) S_K1 :: w a -> SRep w (K1 i a) S_M1 :: SMeta i t -> SRep w f -> SRep w (M1 i t f) S_ST :: c => SRep w f -> SRep w (c :=>: f)--type GenericSy a = (Generic a, Sy (Rep a))+deriving instance (forall a. Show (w a)) => Show (SRep w f)+deriving instance (forall a. Eq (w a)) => Eq (SRep w f)+instance (forall x . NFData (w x)) => NFData (SRep w f) where+ rnf S_U1 = ()+ rnf (S_K1 w) = rnf w+ rnf (S_M1 _ x) = rnf x+ rnf (S_L1 x) = rnf x+ rnf (S_R1 x) = rnf x+ rnf (x :**: y) = rnf x `seq` rnf y+ rnf (S_ST x) = rnf x -fromS :: (GenericSy a, Applicative w) => a -> SRep w (Rep a)-fromS = fromS' . from-fromI :: (GenericSy a) => a -> SRep Identity (Rep a)-fromI = fromS-toS :: (GenericSy a, Comonad w) => SRep w (Rep a) -> a-toS = to . toS'-toI :: (GenericSy a) => SRep Identity (Rep a) -> a-toI = toS+-- |All types supported by "GHC.Generics" are /simplistic/, this+-- constraint just couples their necessary together.+type Simplistic a = (Generic a , GShallow (Rep a)) +-- |Computes the constraint that corresponds to ensuring all+-- leaves of a representation satisfy a given constraint.+-- For example,+--+-- > OnLeaves Eq (Rep (Either a b)) = (Eq a , Eq b)+-- type family OnLeaves (c :: * -> Constraint) (f :: * -> *) :: Constraint where OnLeaves c V1 = () OnLeaves c U1 = ()@@ -67,7 +127,202 @@ OnLeaves c (M1 i p f) = OnLeaves c f OnLeaves c (d :=>: f) = Implies d (OnLeaves c f) +-- |Retrieves the datatype name for a representation.+-- /WARNING; UNSAFE/ this function only works if @f@ is the representation of+-- a type constructed with "GHC.Generics" builtin mechanisms.+repDatatypeName :: SRep w f -> String+repDatatypeName (S_M1 x@SM_D _)+ = getDatatypeName x+repDatatypeName (S_M1 _ x)+ = repDatatypeName x+repDatatypeName (S_L1 x)+ = repDatatypeName x+repDatatypeName (S_R1 x)+ = repDatatypeName x+repDatatypeName _+ = error "Please; use GHC's deriving mechanism. This keeps M1's at the top of the Rep"++-- |Retrieves the constructor name for a representation.+-- /WARNING; UNSAFE/ this function only works if @f@ is the representation of+-- a type constructed with "GHC.Generics" builtin mechanisms.+repConstructorName :: SRep w f -> String+repConstructorName (S_M1 x@SM_C _)+ = getConstructorName x+repConstructorName (S_M1 _ x)+ = repConstructorName x+repConstructorName (S_L1 x)+ = repConstructorName x+repConstructorName (S_R1 x)+ = repConstructorName x+repConstructorName _+ = error "Please; use GHC's deriving mechanism. This keeps M1's at the top of the Rep"++-- |Zips two representations together if they are made up of+-- the same constructor. For example,+--+-- > zipSRep (fromS (: 1 [])) (fromS (: 2 (: 3 [])))+-- > == Just (fromS (: (1 , 2) ([] , [3])))+-- >+-- > zipSRep (fromS (: 1 [])) (fromS [])+-- > == Nothing+zipSRep :: SRep w f -> SRep z f -> Maybe (SRep (w :*: z) f)+zipSRep S_U1 S_U1 = return S_U1+zipSRep (S_L1 x) (S_L1 y) = S_L1 <$> zipSRep x y+zipSRep (S_R1 x) (S_R1 y) = S_R1 <$> zipSRep x y+zipSRep (S_M1 m x) (S_M1 _ y) = S_M1 m <$> zipSRep x y+zipSRep (x1 :**: x2) (y1 :**: y2) = (:**:) <$> (zipSRep x1 y1) <*> (zipSRep x2 y2)+zipSRep (S_K1 x) (S_K1 y) = return $ S_K1 (x :*: y)+zipSRep _ _ = Nothing++-- |Performs a /crush/ over the leaves of a 'SRep' carrying a constraint+-- around.+repLeavesC :: (OnLeaves c rep)+ => Proxy c+ -> (forall x . c x => w x -> r) -- ^ leaf extraction+ -> (r -> r -> r) -- ^ join product+ -> r -- ^ empty+ -> SRep w rep -> r+repLeavesC _ _ _ e S_U1 = e+repLeavesC p l j e (S_L1 x) = repLeavesC p l j e x+repLeavesC p l j e (S_R1 x) = repLeavesC p l j e x+repLeavesC p l j e (S_M1 _ x) = repLeavesC p l j e x+repLeavesC p l j e (x :**: y) = j (repLeavesC p l j e x) (repLeavesC p l j e y)+repLeavesC _ l _ _ (S_K1 x) = l x+repLeavesC p l j e (S_ST x) = repLeavesC p l j e x+++-- |Performs a /crush/ over the leaves of a 'SRep'+repLeaves :: (forall x . w x -> r) -- ^ leaf extraction+ -> (r -> r -> r) -- ^ join product+ -> r -- ^ empty+ -> SRep w rep -> r+repLeaves _ _ e S_U1 = e+repLeaves l j e (S_L1 x) = repLeaves l j e x+repLeaves l j e (S_R1 x) = repLeaves l j e x+repLeaves l j e (S_M1 _ x) = repLeaves l j e x+repLeaves l j e (x :**: y) = j (repLeaves l j e x) (repLeaves l j e y)+repLeaves l _ _ (S_K1 x) = l x+repLeaves l j e (S_ST x) = repLeaves l j e x++-- |Example of 'repLeaves' that places the values of @w@ inside+-- a list.+repLeavesList :: SRep w rep -> [Exists w]+repLeavesList = repLeaves ((:[]) . Exists) (++) []++-- |Maps a function over a representation taking into+-- account that the leaves of the representation satisfy+-- a given constraint.+repMapCM :: (Monad m , OnLeaves c rep)+ => Proxy c -- ^ Which constraint shall be threaded through+ -> (forall y . c y => f y -> m (g y))+ -> SRep f rep -> m (SRep g rep)+repMapCM _p _f (S_U1) = return S_U1+repMapCM _p f (S_K1 x) = S_K1 <$> f x+repMapCM p f (S_M1 m x) = S_M1 m <$> repMapCM p f x+repMapCM p f (S_L1 x) = S_L1 <$> repMapCM p f x+repMapCM p f (S_R1 x) = S_R1 <$> repMapCM p f x+repMapCM p f (x :**: y) = (:**:) <$> repMapCM p f x <*> repMapCM p f y+repMapCM p f (S_ST x) = S_ST <$> repMapCM p f x ++-- |Maps a monadic function over the representation+repMapM :: (Monad m)+ => (forall y . f y -> m (g y))+ -> SRep f rep -> m (SRep g rep)+repMapM _f (S_U1) = return S_U1+repMapM f (S_K1 x) = S_K1 <$> f x+repMapM f (S_M1 m x) = S_M1 m <$> repMapM f x+repMapM f (S_L1 x) = S_L1 <$> repMapM f x+repMapM f (S_R1 x) = S_R1 <$> repMapM f x+repMapM f (S_ST x) = S_ST <$> repMapM f x+repMapM f (x :**: y)+ = (:**:) <$> repMapM f x <*> repMapM f y++-- |Maps a simple functino over the representation+repMap :: (forall y . f y -> g y)+ -> SRep f rep -> SRep g rep+repMap f = runIdentity . repMapM (return . f)++--------------------------------++-- |Identity functor+newtype I x = I { unI :: x }+ deriving Eq++instance Show x => Show (I x) where+ showsPrec p (I x) = showParen (p > 10) $ showString "I " . showsPrec 11 x+instance Functor I where+ fmap f (I x) = I (f x)+instance Applicative I where+ pure = I+ I f <*> I x = I (f x)+instance Monad I where+ I x >>= f = f x++-- |Shallow conversion between "GHC.Generics" representation+-- and 'SRep'; The 'fromS' and 'toS' functions provide the+-- toplevel api.+class GShallow f where+ sfrom :: f x -> SRep I f+ sto :: SRep I f -> f x++instance GShallow U1 where+ sfrom U1 = S_U1+ sto S_U1 = U1++instance (GShallow f , GShallow g) => GShallow (f :+: g) where+ sfrom (L1 x) = S_L1 (sfrom x)+ sfrom (R1 x) = S_R1 (sfrom x)+ sto (S_L1 x) = L1 (sto x)+ sto (S_R1 x) = R1 (sto x)++instance (GShallow f , GShallow g) => GShallow (f :*: g) where+ sfrom (x :*: y) = sfrom x :**: sfrom y+ sto (x :**: y) = sto x :*: sto y++instance (GShallow f , GMeta i c) => GShallow (M1 i c f) where+ sfrom (M1 x) = S_M1 smeta (sfrom x)+ sto (S_M1 _ x) = M1 (sto x)++instance GShallow (K1 R x) where+ sfrom (K1 x) = S_K1 (I x)+ sto (S_K1 (I x)) = K1 x++-- |Converts a value of a generic type directly to its+-- (shallow) simplistic representation.+fromS :: (Simplistic a) => a -> SRep I (Rep a)+fromS = sfrom . from++-- |Converts a simplistic representation back to its corresponding+-- value of type @a@.+toS :: (Simplistic a) => SRep I (Rep a) -> a+toS = to . sto++-- TODO: Study whether it makes sense to add rules+-- and inline pragmas for performance.+-- {-# RULES "sfrom/sto" forall x. sfrom (sto x) = x #-}+-- {-# RULES "sto/sfrom" forall x. sto (sfrom x) = x #-}++---------------------------------------+---------------------------------------+-- Representation of `* -> *` types --+---------------------------------------+---------------------------------------++-- $simplistic1+--+-- "GHC.Generics" provides 'Rep' for types of kind @*@+-- and 'Rep1' for types of kind @* -> *@. Similarly,+-- we also provide 'SRep1' for a closed-universe interpretation+-- of 'Rep1'. It is worth noting the support is limitted and+-- we have not yet written combinators for 'SRep1' like we+-- did for 'SRep'. An example usage of 'SRep1' can be found+-- in "Generics.Simplistic.Derive.Functor".+ infixr 5 :***:++-- |Similar to 'SRep', but is indexed over the functors that+-- make up a 'Rep1', used to explicitely encode types with+-- one parameter. data SRep1 f x where S1_U1 :: SRep1 U1 x S1_L1 :: SRep1 f x -> SRep1 (f :+: g) x@@ -80,12 +335,7 @@ S1_Rec :: f x -> SRep1 (Rec1 f) x S1_Comp :: f (SRep1 g x) -> SRep1 (f :.: g) x -type GenericSy1 f = (Generic1 f, Sy1 (Rep1 f))--fromS1 :: (GenericSy1 f) => f a -> SRep1 (Rep1 f) a-fromS1 = fromS1' . from1-toS1 :: (GenericSy1 f) => SRep1 (Rep1 f) a -> f a-toS1 = to1 . toS1'+type Simplistic1 f = (Generic1 f, GShallow1 (Rep1 f)) type family OnLeaves1 (c :: * -> Constraint) (r :: (* -> *) -> Constraint) (f :: * -> *) :: Constraint where@@ -100,74 +350,48 @@ OnLeaves1 c r (Rec1 f) = r f OnLeaves1 c r (f :.: g) = (r f, OnLeaves1 c r g) --- Internal instances-class SMety i t where- smeta :: SMeta i t-instance Datatype d => SMety D d where- smeta = SM_D-instance Constructor c => SMety C c where- smeta = SM_C-instance Selector s => SMety S s where- smeta = SM_S-class Sy f where- fromS' :: Applicative w => f a -> SRep w f- toS' :: Comonad w => SRep w f -> f a-instance Sy V1 where- fromS' = undefined- toS' = undefined-instance Sy U1 where- fromS' U1 = S_U1- toS' S_U1 = U1-instance (Sy f, Sy g) => Sy (f :+: g) where- fromS' (L1 x) = S_L1 (fromS' x)- fromS' (R1 y) = S_R1 (fromS' y)- toS' (S_L1 x) = L1 (toS' x)- toS' (S_R1 y) = R1 (toS' y)-instance (Sy f, Sy g) => Sy (f :*: g) where- fromS' (x :*: y) = fromS' x :**: fromS' y- toS' (x :**: y) = toS' x :*: toS' y-instance Sy (K1 i a) where- fromS' (K1 x) = S_K1 (pure x)- toS' (S_K1 x) = K1 (extract x)-instance (SMety i t, Sy f) => Sy (M1 i t f) where- fromS' (M1 x) = S_M1 smeta (fromS' x)- toS' (S_M1 _ x) = M1 (toS' x)-instance (c => Sy f) => Sy (c :=>: f) where- fromS' (SuchThat x) = S_ST (fromS' x)- toS' (S_ST x) = SuchThat (toS' x)+-- |Converts a value of a generic type directly to its+-- (shallow) simplistic1 representation with a parameter.+fromS1 :: (Simplistic1 f) => f x -> SRep1 (Rep1 f) x+fromS1 = sfrom1 . from1 -class Sy1 f where- fromS1' :: f a -> SRep1 f a- toS1' :: SRep1 f a -> f a-instance Sy1 V1 where- fromS1' = undefined- toS1' = undefined-instance Sy1 U1 where- fromS1' U1 = S1_U1- toS1' S1_U1 = U1-instance (Sy1 f, Sy1 g) => Sy1 (f :+: g) where- fromS1' (L1 x) = S1_L1 (fromS1' x)- fromS1' (R1 y) = S1_R1 (fromS1' y)- toS1' (S1_L1 x) = L1 (toS1' x)- toS1' (S1_R1 y) = R1 (toS1' y)-instance (Sy1 f, Sy1 g) => Sy1 (f :*: g) where- fromS1' (x :*: y) = fromS1' x :***: fromS1' y- toS1' (x :***: y) = toS1' x :*: toS1' y-instance Sy1 (K1 i a) where- fromS1' (K1 x) = S1_K1 x- toS1' (S1_K1 x) = K1 x-instance (SMety i t, Sy1 f) => Sy1 (M1 i t f) where- fromS1' (M1 x) = S1_M1 smeta (fromS1' x)- toS1' (S1_M1 _ x) = M1 (toS1' x)-instance (c => Sy1 f) => Sy1 (c :=>: f) where- fromS1' (SuchThat x) = S1_ST (fromS1' x)- toS1' (S1_ST x) = SuchThat (toS1' x)-instance Sy1 Par1 where- fromS1' (Par1 x) = S1_Par x- toS1' (S1_Par x) = Par1 x-instance Sy1 (Rec1 f) where- fromS1' (Rec1 x) = S1_Rec x- toS1' (S1_Rec x) = Rec1 x-instance (Functor f, Sy1 g) => Sy1 (f :.: g) where- fromS1' (Comp1 x) = S1_Comp (fmap fromS1' x)- toS1' (S1_Comp x) = Comp1 (fmap toS1' x)+-- |Converts a simplistic1 representation back to its corresponding+-- value of type @a@.+toS1 :: (Simplistic1 f) => SRep1 (Rep1 f) x -> f x+toS1 = to1 . sto1++class GShallow1 f where+ sfrom1 :: f a -> SRep1 f a+ sto1 :: SRep1 f a -> f a+instance GShallow1 V1 where+ sfrom1 = undefined+ sto1 = undefined+instance GShallow1 U1 where+ sfrom1 U1 = S1_U1+ sto1 S1_U1 = U1+instance (GShallow1 f, GShallow1 g) => GShallow1 (f :+: g) where+ sfrom1 (L1 x) = S1_L1 (sfrom1 x)+ sfrom1 (R1 y) = S1_R1 (sfrom1 y)+ sto1 (S1_L1 x) = L1 (sto1 x)+ sto1 (S1_R1 y) = R1 (sto1 y)+instance (GShallow1 f, GShallow1 g) => GShallow1 (f :*: g) where+ sfrom1 (x :*: y) = sfrom1 x :***: sfrom1 y+ sto1 (x :***: y) = sto1 x :*: sto1 y+instance GShallow1 (K1 i a) where+ sfrom1 (K1 x) = S1_K1 x+ sto1 (S1_K1 x) = K1 x+instance (GMeta i t, GShallow1 f) => GShallow1 (M1 i t f) where+ sfrom1 (M1 x) = S1_M1 smeta (sfrom1 x)+ sto1 (S1_M1 _ x) = M1 (sto1 x)+instance (c => GShallow1 f) => GShallow1 (c :=>: f) where+ sfrom1 (SuchThat x) = S1_ST (sfrom1 x)+ sto1 (S1_ST x) = SuchThat (sto1 x)+instance GShallow1 Par1 where+ sfrom1 (Par1 x) = S1_Par x+ sto1 (S1_Par x) = Par1 x+instance GShallow1 (Rec1 f) where+ sfrom1 (Rec1 x) = S1_Rec x+ sto1 (S1_Rec x) = Rec1 x+instance (Functor f, GShallow1 g) => GShallow1 (f :.: g) where+ sfrom1 (Comp1 x) = S1_Comp (fmap sfrom1 x)+ sto1 (S1_Comp x) = Comp1 (fmap sto1 x)
+ src/Generics/Simplistic/Deep.hs view
@@ -0,0 +1,390 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE UndecidableSuperClasses #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wno-orphans #-}+-- |Deep representation for 'SRep'+module Generics.Simplistic.Deep+ ( -- * (Co)Free (Co)Monad and its cousins+ HolesAnn(..)+ , SFix , pattern SFix , pattern Prim+ , SFixAnn , pattern SFixAnn , pattern PrimAnn+ , Holes , pattern Roll , pattern Hole+ -- ** Constraints+ , CompoundCnstr , PrimCnstr+ -- ** Coercions+ , holesToSFix , sfixToHoles+ -- ** Maps, zips and folds+ , holesMapAnn , holesMap , holesMapM , holesMapAnnM , getAnn+ , holesJoin , holesSize, holesHolesList+ , holesRefineM , holesRefineHoles , holesRefineHolesM+ , synthesize , synthesizeM , cataM+ -- ** Anti-Unification+ , lgg+ -- ** Conversion+ , Deep(..) , GDeep(..)+ ) where++import Data.Proxy+-- import qualified Data.Set as S (Set, fromList)+import Control.Monad.Identity+import Control.DeepSeq+import GHC.Generics (from , to)+import Unsafe.Coerce++import Generics.Simplistic+import Generics.Simplistic.Util++-- Useful constraints++type PrimCnstr kappa fam b+ = (Elem b kappa , NotElem b fam)++type CompoundCnstr kappa fam a+ = (Elem a fam , NotElem a kappa , Generic a)++-- |The cofree comonad and free monad on the same type;+-- this allows us to use the same recursion operator+-- for everything.+data HolesAnn kappa fam ann h a where+ Hole' :: ann a -- ^ Annotation+ -> h a -> HolesAnn kappa fam ann h a+ Prim' :: (PrimCnstr kappa fam a)+ => ann a -- ^ Annotation+ -> a -> HolesAnn kappa fam ann h a+ Roll' :: (CompoundCnstr kappa fam a)+ => ann a -- ^ Annotation+ -> SRep (HolesAnn kappa fam ann h) (Rep a)+ -> HolesAnn kappa fam ann h a++instance (All Eq kappa , EqHO h) => EqHO (Holes kappa fam h) where+ eqHO x y = all (exElim $ uncurry' go) $ holesHolesList (lgg x y)+ where+ go :: Holes kappa fam h a -> Holes kappa fam h a -> Bool+ go (Hole h1) (Hole h2) = eqHO h1 h2+ go _ _ = False++instance (All Eq kappa , EqHO h) => Eq (Holes kappa fam h t) where+ (==) = eqHO++-- |Deep representations are easily achieved by forbiding+-- the 'Hole'' constructor and providing unit annotations.+type SFix kappa fam = HolesAnn kappa fam U1 V1++pattern SFix :: () => (CompoundCnstr kappa fam a)+ => SRep (SFix kappa fam) (Rep a)+ -> SFix kappa fam a+pattern SFix x = Roll x+{-# COMPLETE SFix , Prim #-}++-- |A tree with holes has unit annotations+type Holes kappa fam = HolesAnn kappa fam U1++pattern Hole :: h a -> Holes kappa fam h a+pattern Hole x = Hole' U1 x++pattern Prim :: () => (PrimCnstr kappa fam a)+ => a -> Holes kappa fam h a+pattern Prim a = Prim' U1 a++pattern Roll :: () => (CompoundCnstr kappa fam a)+ => SRep (Holes kappa fam h) (Rep a)+ -> Holes kappa fam h a+pattern Roll x = Roll' U1 x+{-# COMPLETE Hole , Prim , Roll #-}++-- |Annotated fixpoints are also easy; forbid the 'Hole''+-- constructor but add something to every 'Roll' of+-- the representation.+type SFixAnn kappa fam ann = HolesAnn kappa fam ann V1++pattern PrimAnn :: () => (PrimCnstr kappa fam a)+ => ann a -> a -> SFixAnn kappa fam ann a+pattern PrimAnn ann a = Prim' ann a++pattern SFixAnn :: () => (CompoundCnstr kappa fam a)+ => ann a+ -> SRep (SFixAnn kappa fam ann) (Rep a)+ -> SFixAnn kappa fam ann a+pattern SFixAnn ann x = Roll' ann x+{-# COMPLETE SFixAnn , PrimAnn #-}++---------------+-- Coercions --+---------------++sfixToHoles :: SFix kappa fam at -> Holes kappa fam h at+sfixToHoles = unsafeCoerce++holesToSFix :: Holes kappa fam V1 at -> SFix kappa fam at+holesToSFix = id++------------+-- NFData --+------------++-- VCM: QUESTION: DDoes it make sense to have this here?+-- I need it in /hdiff/, and I can see how it can be useful.+-- @trupill, do you prefer to keep this or trash this?++instance (forall x . NFData (ann x) , forall x . NFData (h x))+ => NFData (HolesAnn kappa fam ann h f) where+ rnf (Prim' ann _) = rnf ann+ rnf (Hole' ann h) = rnf ann `seq` rnf h+ rnf (Roll' ann x) = rnf ann `seq` rnf x++instance NFData (V1 x) where+ rnf _ = ()++instance NFData (U1 x) where+ rnf U1 = ()++----------------------+-- Useful Functions --+----------------------++-- |Retrieves the annotation inside a 'HolesAnn';+-- this is the counit of the comonad.+getAnn :: HolesAnn kappa fam ann h a -> ann a+getAnn (Hole' ann _) = ann+getAnn (Prim' ann _) = ann+getAnn (Roll' ann _) = ann++-- TODO: swap parameters+-- |Maps over a 'HolesAnn' treating annotations and holes+-- independently.+holesMapAnnM :: (Monad m)+ => (forall x . f x -> m (g x)) -- ^ Function to transform holes+ -> (forall x . ann x -> m (psi x)) -- ^ Function to transform annotations+ -> HolesAnn kappa fam ann f a -> m (HolesAnn kappa fam psi g a)+holesMapAnnM f g (Hole' a x) = Hole' <$> g a <*> f x+holesMapAnnM _ g (Prim' a x) = flip Prim' x <$> g a+holesMapAnnM f g (Roll' a x) = Roll' <$> g a <*> repMapM (holesMapAnnM f g) x++-- |Maps over 'HolesAnn' maintaining annotations intact.+holesMapM :: (Monad m)+ => (forall x . f x -> m (g x))+ -> HolesAnn kappa fam ann f a -> m (HolesAnn kappa fam ann g a)+holesMapM f = holesMapAnnM f return++-- |Maps over the holes in a 'HolesAnn'+holesMap :: (forall x . f x -> g x)+ -> HolesAnn kappa fam ann f a -> HolesAnn kappa fam ann g a+holesMap f = runIdentity . holesMapM (return . f)++-- |Maps over holes and annotations in a 'HolesAnn'+holesMapAnn :: (forall x . f x -> g x)+ -> (forall x . ann x -> phi x)+ -> HolesAnn kappa fam ann f a -> HolesAnn kappa fam phi g a+holesMapAnn f g = runIdentity . holesMapAnnM (return . f) (return . g)++-- |Monadic multiplication+holesJoin :: HolesAnn kappa fam ann (HolesAnn kappa fam ann f) a+ -> HolesAnn kappa fam ann f a+holesJoin (Hole' _ x) = x+holesJoin (Prim' a x) = Prim' a x+holesJoin (Roll' a x) = Roll' a (repMap holesJoin x)++-- |Computes the list of holes in a 'HolesAnn'+holesHolesList :: HolesAnn kappa fam ann f a -> [Exists f]+holesHolesList (Hole' _ x) = [Exists x]+holesHolesList (Prim' _ _) = []+holesHolesList (Roll' _ x) = concatMap (exElim holesHolesList) $ repLeavesList x++{-+holesHolesSet :: (Ord (Exists f)) => Holes kappa fam f a -> S.Set (Exists f)+holesHolesSet = S.fromList . holesHolesList+-}++-- TODO: Implement holesMap in terms of refine; its much better!++-- |Refines holes using a monadic action+holesRefineHolesM :: (Monad m)+ => (forall b . f b -> m (Holes kappa fam g b))+ -> Holes kappa fam f a+ -> m (Holes kappa fam g a)+holesRefineHolesM f = fmap holesJoin . holesMapM f++-- |Refine holes with a simple action+holesRefineHoles :: (forall b . f b -> Holes kappa fam g b)+ -> Holes kappa fam f a+ -> Holes kappa fam g a+holesRefineHoles f = holesJoin . runIdentity . holesMapM (return . f)++-- |Refine holes and primitives+holesRefineM :: (Monad m)+ => (forall b . f b -> m (Holes kappa fam g b))+ -> (forall b . (PrimCnstr kappa fam b)+ => b -> m (Holes kappa fam g b))+ -> Holes kappa fam f a+ -> m (Holes kappa fam g a)+holesRefineM f _ (Hole x) = f x+holesRefineM _ g (Prim x) = g x+holesRefineM f g (Roll x) = Roll <$> repMapM (holesRefineM f g) x++-- |Counts how many 'Prim's and 'Roll's are inside a 'HolesAnn'.+holesSize :: HolesAnn kappa fam ann h a -> Int+holesSize (Hole' _ _) = 0+holesSize (Prim' _ _) = 1+holesSize (Roll' _ x) = 1 + sum (map (exElim holesSize) $ repLeavesList x)++-- |Catamorphism over 'HolesAnn'+cataM :: (Monad m)+ => (forall b . (CompoundCnstr kappa fam b)+ => ann b -> SRep phi (Rep b) -> m (phi b)) -- ^ How to handle recursion+ -> (forall b . (PrimCnstr kappa fam b)+ => ann b -> b -> m (phi b)) -- ^ How to handle primitivies+ -> (forall b . ann b -> h b -> m (phi b)) -- ^ How to handle holes+ -> HolesAnn kappa fam ann h a+ -> m (phi a)+cataM f g h (Roll' ann x) = repMapM (cataM f g h) x >>= f ann+cataM _ g _ (Prim' ann x) = g ann x+cataM _ _ h (Hole' ann x) = h ann x++-- |Synthetization of attributes+synthesizeM :: (Monad m)+ => (forall b . (CompoundCnstr kappa fam b)+ => ann b -> SRep phi (Rep b) -> m (phi b)) -- ^ How to handle recursion+ -> (forall b . (PrimCnstr kappa fam b)+ => ann b -> b -> m (phi b)) -- ^ How to handle primitives+ -> (forall b . ann b -> h b -> m (phi b)) -- ^ How to handle holes+ -> HolesAnn kappa fam ann h a+ -> m (HolesAnn kappa fam phi h a)+synthesizeM f g h = cataM (\ann r -> flip Roll' r+ <$> f ann (repMap getAnn r))+ (\ann b -> flip Prim' b <$> g ann b)+ (\ann r -> flip Hole' r <$> h ann r)++-- |Simpler version of 'synthesizeM' working over the /Identity/ monad.+synthesize :: (forall b . (CompoundCnstr kappa fam b)+ => ann b -> SRep phi (Rep b) -> phi b)+ -> (forall b . (PrimCnstr kappa fam b)+ => ann b -> b -> phi b)+ -> (forall b . ann b -> h b -> phi b)+ -> HolesAnn kappa fam ann h a+ -> HolesAnn kappa fam phi h a+synthesize f g h = runIdentity+ . synthesizeM (\ann -> return . f ann)+ (\ann -> return . g ann)+ (\ann -> return . h ann)++-- Anti unification is so simple it doesn't+-- deserve its own module++-- |Computes the /least general generalization/ of two+-- trees.+lgg :: forall kappa fam h i a+ . (All Eq kappa)+ => Holes kappa fam h a -> Holes kappa fam i a+ -> Holes kappa fam (Holes kappa fam h :*: Holes kappa fam i) a+lgg (Prim x) (Prim y)+ | weq (Proxy :: Proxy kappa) x y = Prim x+ | otherwise = Hole (Prim x :*: Prim y)+lgg x@(Roll rx) y@(Roll ry) =+ case zipSRep rx ry of+ Nothing -> Hole (x :*: y)+ Just r -> Roll (repMap (uncurry' lgg) r)+lgg x y = Hole (x :*: y)++----------------------+-- Deep translation --+----------------------++{- It is possible to have a simler GDeep; relying on+-- GShallow. I'll test performance later.++class GDeep' fam prim isPrim a where+ gdfrom' :: Proxy isPrim -> a -> SFix fam prim a+ gdto' :: Proxy isPrim -> SFix fam prim a -> a++instance (CompoundCnstr fam prim a , GDeep fam prim a)+ => GDeep' fam prim 'False a where+ gdfrom' _ a = gdfrom $ a+ gdto' _ x = gdto x++instance (PrimCnstr fam prim a) => GDeep' fam prim 'True a where+ gdfrom' _ a = Prim a+ gdto' _ (Prim a) = a++class GDeep fam prim a where+ gdfrom :: a -> SFix fam prim a+ gdto :: SFix fam prim a -> a++instance GDeep' fam prim (IsElem a prim) a => GDeep fam prim a where+ gdfrom = gdfrom' (Proxy :: Proxy (IsElem a prim))+ gdto = gdto' (Proxy :: Proxy (IsElem a prim))++dfrom :: forall fam prim a+ . (CompoundCnstr fam prim a)+ => a -> SFix fam prim a+dfrom = SFix+ . runIdentity+ . repMapCM (Proxy :: Proxy (GDeep fam prim))+ (\(I x) -> return $ gdfrom x)+ . fromS++-}++class (CompoundCnstr kappa fam a) => Deep kappa fam a where+ dfrom :: a -> SFix kappa fam a+ default dfrom :: (GDeep kappa fam (Rep a)) => a -> SFix kappa fam a+ dfrom = SFix . gdfrom . from++ dto :: SFix kappa fam a -> a+ default dto :: (GDeep kappa fam (Rep a)) => SFix kappa fam a -> a+ dto (SFix x) = to . gdto $ x++class GDeep kappa fam f where+ gdfrom :: f x -> SRep (SFix kappa fam) f+ gdto :: SRep (SFix kappa fam) f -> f x++class GDeepAtom kappa fam (isPrim :: Bool) a where+ gdfromAtom :: Proxy isPrim -> a -> SFix kappa fam a+ gdtoAtom :: Proxy isPrim -> SFix kappa fam a -> a++instance (CompoundCnstr kappa fam a , Deep kappa fam a)+ => GDeepAtom kappa fam 'False a where+ gdfromAtom _ a = dfrom $ a+ gdtoAtom _ x = dto x++instance (PrimCnstr kappa fam a) => GDeepAtom kappa fam 'True a where+ gdfromAtom _ a = Prim a+ gdtoAtom _ (Prim a) = a++instance (GDeepAtom kappa fam (IsElem a kappa) a) => GDeep kappa fam (K1 R a) where+ gdfrom (K1 a) = S_K1 (gdfromAtom (Proxy :: Proxy (IsElem a kappa)) a)+ gdto (S_K1 a) = K1 (gdtoAtom (Proxy :: Proxy (IsElem a kappa)) a)++instance GDeep kappa fam U1 where+ gdfrom U1 = S_U1+ gdto S_U1 = U1++instance (GDeep kappa fam f , GDeep kappa fam g) => GDeep kappa fam (f :*: g) where+ gdfrom (x :*: y) = (gdfrom x) :**: (gdfrom y)+ gdto (x :**: y) = (gdto x) :*: (gdto y)++instance (GDeep kappa fam f , GDeep kappa fam g) => GDeep kappa fam (f :+: g) where+ gdfrom (L1 x) = S_L1 (gdfrom x)+ gdfrom (R1 x) = S_R1 (gdfrom x)++ gdto (S_L1 x) = L1 (gdto x)+ gdto (S_R1 x) = R1 (gdto x)++instance (GMeta i c , GDeep kappa fam f) => GDeep kappa fam (M1 i c f) where+ gdfrom (M1 x) = S_M1 smeta (gdfrom x)+ gdto (S_M1 _ x) = M1 (gdto x)
+ src/Generics/Simplistic/Deep/TH.hs view
@@ -0,0 +1,315 @@+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE CPP #-}+-- |This module provides some Template Haskell functionality to+-- help out the declaration of 'Deep' instances.+--+-- Note that we chose to not automate the whole process on purpose.+-- Sometimes the user will need to define standalone 'Generic'+-- instances for some select types in the family, some other times+-- the user might want better control over naming, for example.+-- Consequently, the most adaptable option is to provide+-- two TH utilities:+--+-- 1. Unfolding a family into a list of types until a fixpoint is reached,+-- given in 'unfoldFamilyInto'+-- 2. Declaring 'Deep' for a list of types, given in 'declareDeepFor'+--+-- The stepts in between unfolding the family and declaring 'Deep' vary+-- too much from case to case and hence, must be manually executed.+-- Let us run through a simple example, which involves mutual+-- recursion and type synonyms in the AST of a pseudo-language.+--+-- > data Stmt var+-- > = SAssign var (Exp var)+-- > | SIf (Exp var) (Stmt var) (Stmt var)+-- > | SSeq (Stmt var) (Stmt var)+-- > | SReturn (Exp var)+-- > | SDecl (Decl var)+-- > | SSkip+-- > deriving (Show, Generic)+-- >+-- > data ODecl var+-- > = DVar var+-- > | DFun var var (Stmt var)+-- > deriving (Show, Generic)+-- >+-- > type Decl x = TDecl x+-- > type TDecl x = ODecl x+-- >+-- > data Exp var+-- > = EVar var+-- > | ECall var (Exp var)+-- > | EAdd (Exp var) (Exp var)+-- > | ESub (Exp var) (Exp var)+-- > | ELit Int+-- > deriving (Show, Generic)+--+-- Now say we want to use some code written with /generics-simplistic/+-- over these datatypes above. We must declare the 'Deep'+-- instances for the types in the family and "GHC.Generics"+-- takes care of the rest.+--+-- The first step is in defining @Prim@ and @Fam@, which+-- will be type-level lists with the primitive types and the non-primitive,+-- or compound, types.+--+-- An easy way to gather /all/ types involved in the family is with+-- 'unfoldFamilyInto', like:+--+-- > unfoldFamilyInto "stmtFam" [t| Stmt Int |]+--+-- The call above will be expanded into:+--+-- > stmtFam :: [String]+-- > stmtFam = ["Generics.Simplistic.Example.Exp Int"+-- > ,"Generics.Simplistic.Example.ODecl Int"+-- > ,"Generics.Simplistic.Example.Stmt Int"+-- > ,"Int"+-- > ]+--+-- Which can then be inspected with GHCi and, with+-- some elbow-grease (or test-editting macros!) we can+-- easily generate the necessary type-level lists:+--+-- > type Fam = '[Generics.Simplistic.Example.Exp Int+-- > ,Generics.Simplistic.Example.ODecl Int+-- > ,Generics.Simplistic.Example.Stmt Int+-- > ]+-- >+-- > type Prim = '[Int]+--+-- Finally, we are ready to call 'deriveDeepFor' and get+-- the instances declared.+--+-- > deriveDeepFor ''Prim ''Fam+--+-- The TH code above expands to:+--+-- > instance Deep Prim Fam (Exp Int)+-- > instance Deep Prim Fam (ODecl Int)+-- > instance Deep Prim Fam (Stmt Int)+--+-- This workflow is crucial to be able to work+-- with large mutually recursive families, and it becomes+-- especially easy if coupled with+-- a text editor with good macro support (read emacs and vim).+--+module Generics.Simplistic.Deep.TH+ ( unfoldFamilyInto+ , deriveDeepFor+ , deriveInstancesWith+ ) where++import Control.Monad.State+import Control.Arrow ((***))++import Language.Haskell.TH hiding (match)+import Language.Haskell.TH.Syntax hiding (lift)++import qualified Data.Set as S++import Generics.Simplistic.Deep++-- |Lists all the necessary types that should+-- have 'Generic' and 'Deep' instances. For example,+--+-- > data Rose2 a b = Fork (Either a b) [Rose2 a b]+-- > unfoldFamilyInto 'rose2tys [t| Rose2 Int Char |]+--+-- Will yield the following code:+--+-- > rose2tys :: String+-- > rose2tys = [ "Rose2 Int Char"+-- > , "Either Int Char"+-- > , "[Rose2 Int Char]"+-- > , "Int"+-- > , "Char"+-- > ]+--+-- You should then use some elbow grease or your favorite text editor+-- and its provided macro functionality to produce:+--+-- > type Rose2Prim = '[Int , Char]+-- > type Rose2Fam = '[Rose2 Int Char , Either Int Char , [Rose2 Int Char]]+-- > deriving instance Generic (Rose2 Int Char)+-- > deriving instance Generic (Either Int Char)+-- > instance Deep Rose2Prim Rose2Fam (Rose2 Int Char)+-- > instance Deep Rose2Prim Rose2Fam (Either Int Char)+-- > instance Deep Rose2Prim Rose2Fam [Rose2 Int Char]+--+-- Note that types like @Int@ will appear fully qualified,+-- this will need some renaming.+unfoldFamilyInto :: String -> Q Type -> Q [Dec]+unfoldFamilyInto n first = do+ ty <- first >>= convertType+ allTys <- S.toList <$> execStateT (process ty) S.empty+ listStr <- [t| [String] |]+ return [ SigD (mkName n) listStr+ , FunD (mkName n) [Clause [] (NormalB $ mkExp allTys) []]+ ]+ where+ mkExp :: [STy] -> Exp+ mkExp = ListE . map (LitE . StringL . show . ppr . trevnocType)++-- |Given two type-level lists @Prims@ and @Fam@, will generate+-- @instance Deep Prim Fam f@ for every @f@ in @Fam@.+deriveDeepFor :: Name -> Name -> Q [Dec]+deriveDeepFor pr fam =+ let qprim = return $ ConT pr+ qfam = return $ ConT fam+ in deriveInstancesWith (\t -> [t| Deep $(qprim) $(qfam) $(return t) |]) fam++-- |Given a function @f@ and a type level stored in @fam@,+-- 'deriveInstacesWith' will generate:+--+-- > instance f x+--+-- for each @x@ in @fam@. This function is mostly internal,+-- please check 'deriveDeepFor' and 'deriveGenericFor'.+deriveInstancesWith :: (Type -> Q Type) -- ^ Instance to derive+ -> Name -- ^ fam+ -> Q [Dec]+deriveInstancesWith f fam = do+ tys <- getTypeLevelList fam+ forM tys $ \ty -> do+ instTy <- f ty+ return $ InstanceD Nothing [] instTy []+++getTypeLevelList :: Name -> Q [Type]+getTypeLevelList x = do+ mtyDecl <- reifyDec x+ case mtyDecl of+ Nothing -> fail ("Not a type declaration: " ++ show (ppr x))+ Just (TySynD _ _ ty) -> getTyLL ty+ Just d -> fail ("Not a type-level list: " ++ show (ppr x) ++ show (ppr d))+ where+ getTyLL :: Type -> Q [Type]+ getTyLL (SigT t _) = getTyLL t+ getTyLL PromotedNilT = return []+ getTyLL (AppT (AppT PromotedConsT a) as) = (a:) <$> getTyLL as+ getTyLL t = fail ("Not a type-level list: " ++ show (ppr x) ++ "; " ++ show t)++process :: STy -> StateT (S.Set STy) Q ()+process ty = do+ tys <- get+ if ty `S.member` tys+ then return ()+ else do+ let (tyHd , args) = styFlatten ty+ case tyHd of+ ConST tyName -> do+ tyDecl <- lift (reifyDec tyName)+ case tyDecl of+ Just dec -> processDecl dec args+ Nothing -> return ()+ _ -> fail "Invalid type"++processDecl :: Dec -> [STy] -> StateT (S.Set STy) Q ()+processDecl (DataD _ tyName vars _ cons _) args = do+ modify (S.insert (styApp tyName args))+ let argVal = zip (map tyvarName vars) args+ mapM_ (processCon argVal) cons+processDecl (NewtypeD _ tyName vars _ con _) args = do+ modify (S.insert (styApp tyName args))+ let argVal = zip (map tyvarName vars) args+ processCon argVal con+processDecl (TySynD _ vars ty) args = do+ sty <- convertType ty+ let argVal = zip (map tyvarName vars) args+ process (styReduce argVal sty)+processDecl _ _+ = fail "unknown decl"++processCon :: [(Name , STy)] -> Con -> StateT (S.Set STy) Q ()+processCon argVal con = do+ fields <- mapM (fmap (styReduce argVal) . convertType) (conType con)+ mapM_ process fields++tyvarName :: TyVarBndr -> Name+tyvarName (PlainTV n) = n+tyvarName (KindedTV n _) = n++vbtyTy :: VarBangType -> Type+vbtyTy (_ , _ , t) = t++btyTy :: BangType -> Type+btyTy (_ , t) = t++conType :: Con -> [Type]+conType (NormalC _ btys) = map btyTy btys+conType (RecC _ vbtys) = map vbtyTy vbtys+conType (InfixC tyl _ tyr) = map btyTy [tyl , tyr]+conType (ForallC _ _ c) = conType c+conType (GadtC _ btys _) = map btyTy btys+conType (RecGadtC _ vbtys _) = map vbtyTy vbtys++----------------------++data STy+ = AppST STy STy+ | VarST Name+ | ConST Name+ deriving (Eq , Show, Ord)++#if __GLASGOW_HASKELL__ >= 808+convertType :: (MonadFail m) => Type -> m STy+#else+convertType :: (Monad m) => Type -> m STy+#endif+convertType (AppT a b) = AppST <$> convertType a <*> convertType b+convertType (SigT t _) = convertType t+convertType (VarT n) = return (VarST n)+convertType (ConT n) = return (ConST n)+convertType (ParensT t) = convertType t+convertType ListT = return (ConST (mkName "[]"))+convertType (TupleT n) = return (ConST (mkName $ '(':replicate (n-1) ',' ++ ")"))+convertType t = fail ("convertType: Unsupported Type: " ++ show t)++trevnocType :: STy -> Type+trevnocType (AppST a b) = AppT (trevnocType a) (trevnocType b)+trevnocType (VarST n) = VarT n+trevnocType (ConST n)+ | n == mkName "[]" = ListT+ | isTupleN n = TupleT $ length (show n) - 1+ | otherwise = ConT n+ where isTupleN n0 = take 2 (show n0) == "(,"++-- |Handy substitution function.+--+-- @stySubst t m n@ substitutes m for n within t, that is: t[m/n]+stySubst :: STy -> Name -> STy -> STy+stySubst (AppST a b) m n = AppST (stySubst a m n) (stySubst b m n)+stySubst (ConST a) _ _ = ConST a+stySubst (VarST x) m n+ | x == m = n+ | otherwise = VarST x++-- |Just like subst, but applies a list of substitutions+styReduce :: [(Name , STy)] -> STy -> STy+styReduce parms t = foldr (\(n , m) ty -> stySubst ty n m) t parms++-- |Flattens an application into a list of arguments;+--+-- @styFlatten (AppST (AppST Tree A) B) == (Tree , [A , B])@+styFlatten :: STy -> (STy , [STy])+styFlatten (AppST a b) = id *** (++ [b]) $ styFlatten a+styFlatten sty = (sty , [])++styApp :: Name -> [STy] -> STy+styApp name args = go (ConST name) (reverse args)+ where go t [] = t+ go t (x:xs) = AppST (go t xs) x++-- * Parsing Haskell's AST++reifyDec :: Name -> Q (Maybe Dec)+reifyDec name =+ do info <- reify name+ case info of TyConI dec -> return (Just dec)+ _ -> return Nothing
src/Generics/Simplistic/Derive/Eq.hs view
@@ -1,23 +1,21 @@-{-# language GADTs,- TypeFamilies,- ConstraintKinds,- TypeOperators,- FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-} module Generics.Simplistic.Derive.Eq where -import Data.Functor.Identity+import Data.Proxy+ import Generics.Simplistic+import Generics.Simplistic.Util -geq :: (Applicative w, OnLeaves Eq f)- => SRep w f -> SRep w f -> w Bool-geq S_U1 S_U1 = pure True-geq (S_L1 x) (S_L1 y) = geq x y-geq (S_R1 x) (S_R1 y) = geq x y-geq (x :**: y) (u :**: v) = (&&) <$> geq x u <*> geq y v-geq (S_K1 x) (S_K1 y) = (==) <$> x <*> y-geq (S_M1 _ x) (S_M1 _ y) = geq x y-geq (S_ST x) (S_ST y) = geq x y-geq _ _ = pure False+geq' :: (OnLeaves Eq f) => SRep I f -> SRep I f -> Bool+geq' x y = maybe False sameLeaves $ zipSRep x y+ where+ sameLeaves :: (OnLeaves Eq f) => SRep (I :*: I) f -> Bool+ sameLeaves = repLeavesC (Proxy :: Proxy Eq) (uncurry' (==)) (&&) True -geq' :: (GenericSy a, OnLeaves Eq (Rep a)) => a -> a -> Bool-geq' x y = runIdentity $ geq (fromS x) (fromS y)+geq :: (Generic a, GShallow (Rep a), OnLeaves Eq (Rep a))+ => a -> a -> Bool+geq x y = geq' (fromS x) (fromS y)
src/Generics/Simplistic/Derive/Functor.hs view
@@ -1,23 +1,29 @@-{-# language GADTs,- TypeOperators,- FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-} module Generics.Simplistic.Derive.Functor where import Generics.Simplistic -gfmap :: OnLeaves1 Trivial Functor f+-- TODO: Abstract this away as a repMap1++-- |'SRep1' is a functor+gfmap' :: OnLeaves1 Trivial Functor f => (a -> b) -> SRep1 f a -> SRep1 f b-gfmap _ S1_U1 = S1_U1-gfmap f (S1_L1 x) = S1_L1 (gfmap f x)-gfmap f (S1_R1 x) = S1_R1 (gfmap f x)-gfmap f (x :***: y) = gfmap f x :***: gfmap f y-gfmap f (S1_K1 x) = S1_K1 x-gfmap f (S1_M1 i x) = S1_M1 i (gfmap f x)-gfmap f (S1_ST x) = S1_ST (gfmap f x)-gfmap f (S1_Par x) = S1_Par (f x)-gfmap f (S1_Rec x) = S1_Rec (fmap f x)-gfmap f (S1_Comp x) = S1_Comp (fmap (gfmap f) x)+gfmap' _ S1_U1 = S1_U1+gfmap' f (S1_L1 x) = S1_L1 (gfmap' f x)+gfmap' f (S1_R1 x) = S1_R1 (gfmap' f x)+gfmap' f (x :***: y) = gfmap' f x :***: gfmap' f y+gfmap' _ (S1_K1 x) = S1_K1 x+gfmap' f (S1_M1 i x) = S1_M1 i (gfmap' f x)+gfmap' f (S1_ST x) = S1_ST (gfmap' f x)+gfmap' f (S1_Par x) = S1_Par (f x)+gfmap' f (S1_Rec x) = S1_Rec (fmap f x)+gfmap' f (S1_Comp x) = S1_Comp (fmap (gfmap' f) x) -gfmap' :: (GenericSy1 f, OnLeaves1 Trivial Functor (Rep1 f))- => (a -> b) -> f a -> f b-gfmap' f x = toS1 $ gfmap f $ fromS1 x+-- |The action of f over arrows can be obtained by translating+-- into the generic representation, using the generic+-- 'gfmap'' and translating back to regular representation.+gfmap :: (Simplistic1 f, OnLeaves1 Trivial Functor (Rep1 f))+ => (a -> b) -> f a -> f b+gfmap f = toS1 . gfmap' f . fromS1
src/Generics/Simplistic/Derive/Show.hs view
@@ -1,43 +1,42 @@-{-# language GADTs,- TypeFamilies,- ConstraintKinds,- TypeOperators,- FlexibleContexts,- ScopedTypeVariables,- DeriveGeneric #-}-module Generics.Simplistic.Derive.Show where+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE DeriveGeneric #-}+-- |Derives a generic show, for example+--+-- > data MyList a = MyNil | MyCons { hd :: a, tl :: MyList a } deriving Generic+-- > +-- > myListValue :: MyList Integer+-- > myListValue = MyCons 1 (MyCons 2 (MyCons 3 MyNil))+-- > +-- > instance Show a => Show (MyList a) where+-- > show = gshow+--+-- The code here was adapted from `generic-deriving`+-- https://github.com/dreixel/generic-deriving/blob/master/src/Generics/Deriving/Show.hs+module Generics.Simplistic.Derive.Show (gshow , gshowsPrec) where -import Data.Functor.Identity import Generics.Simplistic import GHC.Generics --- An example-data MyList a = MyNil | MyCons { hd :: a, tl :: MyList a } deriving Generic--myListValue :: MyList Integer-myListValue = MyCons 1 (MyCons 2 (MyCons 3 MyNil))--instance Show a => Show (MyList a) where- show = gshow---- Translated from `generic-deriving`--- https://github.com/dreixel/generic-deriving/blob/master/src/Generics/Deriving/Show.hs- appPrec :: Int appPrec = 2 data Type = Rec | Tup | Pref | Inf String -gshow :: (GenericSy t, OnLeaves Show (Rep t))+gshow :: (Generic t, GShallow (Rep t), OnLeaves Show (Rep t)) => t -> String gshow v = gshowsPrec Pref 0 v "" -gshowsPrec :: (GenericSy t, OnLeaves Show (Rep t))+gshowsPrec :: (Generic t, GShallow (Rep t), OnLeaves Show (Rep t)) => Type -> Int -> t -> ShowS gshowsPrec t n v = gshowsPrec' t n (fromS v) gshowsPrec' :: (OnLeaves Show f)- => Type -> Int -> SRep Identity f -> ShowS+ => Type -> Int -> SRep I f -> ShowS -- "Simple" cases gshowsPrec' _ _ S_U1 = id gshowsPrec' t n (S_L1 x) = gshowsPrec' t n x@@ -54,7 +53,7 @@ gshowsPrec' t@Pref n (a :**: b) = gshowsPrec' t (n+1) a . showChar ' ' . gshowsPrec' t (n+1) b -- The case of metadata-gshowsPrec' t n (S_M1 (SM_C :: SMeta i c) (x :: SRep Identity f)) = +gshowsPrec' _ n (S_M1 (SM_C :: SMeta i c) (x :: SRep I f)) = case fixity of Prefix -> showParen (n > appPrec && not (isNullary x)) ( showString (conName c)@@ -78,7 +77,7 @@ conIsTuple y = tupleName (conName y) where tupleName ('(':',':_) = True tupleName _ = False-gshowsPrec' t n (S_M1 (SM_S :: SMeta i c) (x :: SRep Identity f)) +gshowsPrec' t n (S_M1 (SM_S :: SMeta i c) (x :: SRep I f)) | selName s == "" = --showParen (n > appPrec) (gshowsPrec' t n x) | otherwise = showString (selName s)@@ -87,12 +86,12 @@ where s :: M1 S c f () = undefined gshowsPrec' t n (S_M1 _ x) = gshowsPrec' t n x -isNullary :: SRep Identity a -> Bool+isNullary :: SRep I a -> Bool isNullary S_U1 = True-isNullary (S_L1 x) = error "unnecessary case"-isNullary (S_R1 x) = error "unnecessary case"-isNullary (x :**: y) = False-isNullary (S_K1 x) = False+isNullary (S_L1 _) = error "unnecessary case"+isNullary (S_R1 _) = error "unnecessary case"+isNullary (_ :**: _) = False+isNullary (S_K1 _) = False isNullary (S_M1 t x) = case t of SM_S -> isNullary x _ -> error "unnecessary case"
+ src/Generics/Simplistic/Unify.hs view
@@ -0,0 +1,289 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- |Constraint-based unification algorithm for 'Holes'+module Generics.Simplistic.Unify+ ( -- * Substitution+ Subst , substEmpty , substInsert , substLkup , substApply+ -- * Unification+ , UnifyErr(..) , unify , unify_ , unifyWith , minimize+ ) where++import Data.List (sort)+import qualified Data.Map as M+import Control.Monad.Except+import Control.Monad.State+import Control.Monad.Writer hiding (All)+import Control.Monad.Cont+import Unsafe.Coerce++import Generics.Simplistic.Deep+import Generics.Simplistic.Util++-- |Unification can return succesfully or find either+-- a 'OccursCheck' failure or a 'SymbolClash' failure.+data UnifyErr kappa fam phi :: * where+ -- |The occurs-check fails when the variable in question+ -- occurs within the term its supposed to be unified with.+ OccursCheck :: [Exists phi]+ -> UnifyErr kappa fam phi+ -- |A symbol-clash is thrown when the head of the+ -- two terms is different and neither is a variabe.+ SymbolClash :: Holes kappa fam phi at+ -> Holes kappa fam phi at+ -> UnifyErr kappa fam phi++-- |A substitution is but a map; the existential quantifiers are+-- necessary to ensure we can reuse from "Data.Map"+--+-- Note that we must be able to compare @Exists phi@. This+-- comparison needs to work heterogeneously and it must+-- return 'EQ' only when the contents are in fact equal.+-- Even though we only need this instance for "Data.Map"+--+-- A typical example for @phi@ is @Const Int at@, representing+-- a variable. The @Ord@ instance would then be:+--+-- > instance Ord (Exists (Const Int)) where+-- > compare (Exists (Const x)) (Exists (Const y))+-- > = compare x y+--+type Subst kappa fam phi+ = M.Map (Exists phi) (Exists (Holes kappa fam phi))++-- |Empty substitution+substEmpty :: Subst kappa fam phi+substEmpty = M.empty++-- |Looks a value up in a substitution, see 'substInsert'+substLkup :: (Ord (Exists phi))+ => Subst kappa fam phi -- ^+ -> phi at+ -> Maybe (Holes kappa fam phi at)+substLkup sigma var =+ case M.lookup (Exists var) sigma of+ Nothing -> Nothing+ -- In case we found something, it must be of the same+ -- type as what we got because we only insert+ -- well-typed things.+ -- TODO: Use our sameTy method to remove the unsafeCoerce+ Just (Exists t) -> Just $ unsafeCoerce t++-- |Applies a substitution to a term once; Variables not in the+-- support of the substitution are left untouched.+substApply :: (Ord (Exists phi))+ => Subst kappa fam phi -- ^+ -> Holes kappa fam phi at+ -> Holes kappa fam phi at+substApply sigma = holesJoin+ . holesMap (\v -> maybe (Hole v) id $ substLkup sigma v)++-- |Inserts a point in a substitution. Note how the index of+-- @phi@ /must/ match the index of the term being inserted.+-- This is important when looking up terms because we must+-- 'unsafeCoerce' the existential type variables to return.+--+-- Please, always use this insertion function; or, if you insert+-- by hand, ensure thetype indices match.+substInsert :: (Ord (Exists phi))+ => Subst kappa fam phi -- ^+ -> phi at+ -> Holes kappa fam phi at+ -> Subst kappa fam phi+substInsert sigma v x = M.insert (Exists v) (Exists x) sigma++-- |Unification is done in a monad.+type UnifyM kappa fam phi+ = StateT (Subst kappa fam phi) (Except (UnifyErr kappa fam phi))++-- |Attempts to unify two 'Holes', but ignores+-- which error happened when they could not be unified.+unify_ :: (All Eq kappa , Ord (Exists phi) , EqHO phi)+ => Holes kappa fam phi at -- ^+ -> Holes kappa fam phi at+ -> Maybe (Subst kappa fam phi)+unify_ a = either (const Nothing) Just+ . runExcept . unify a++-- |Attempts to unify two 'Holes'+unify :: (All Eq kappa , Ord (Exists phi) , EqHO phi)+ => Holes kappa fam phi at -- ^+ -> Holes kappa fam phi at+ -> Except (UnifyErr kappa fam phi)+ (Subst kappa fam phi)+unify = unifyWith substEmpty++-- |Attempts to unify two 'Holes' with an already existing+-- substitution+unifyWith :: (All Eq kappa , Ord (Exists phi) , EqHO phi)+ => Subst kappa fam phi -- ^ Starting subst+ -> Holes kappa fam phi at+ -> Holes kappa fam phi at+ -> Except (UnifyErr kappa fam phi)+ (Subst kappa fam phi)+unifyWith sigma x y = execStateT (unifyM x y) sigma++-- Actual unification algorithm; In order to improve efficiency,+-- we first register all equivalences we need to satisfy,+-- then on 'mininize' we do the occurs-check.+unifyM :: forall kappa fam phi at+ . (All Eq kappa , EqHO phi , Ord (Exists phi)) + => Holes kappa fam phi at+ -> Holes kappa fam phi at+ -> UnifyM kappa fam phi ()+unifyM x y = do+ _ <- getEquivs x y+ s <- get+ case minimize s of+ Left vs -> throwError (OccursCheck vs)+ Right s' -> put s'+ where+ getEquivs :: Holes kappa fam phi b+ -> Holes kappa fam phi b+ -> UnifyM kappa fam phi ()+ getEquivs p q = void $ holesMapM (uncurry' getEq) (lgg p q)+ + getEq :: Holes kappa fam phi b+ -> Holes kappa fam phi b+ -> UnifyM kappa fam phi (Holes kappa fam phi b)+ getEq p (Hole var) = record_eq var p >> return p+ getEq p@(Hole var) q = record_eq var q >> return p+ getEq p q | eqHO p q = return p+ | otherwise = throwError (SymbolClash p q)+ + -- Whenever we see a variable being matched against a term+ -- we record the equivalence. First we make sure we did not+ -- record such equivalence yet, otherwise, we recursively thin+ record_eq :: phi b -> Holes kappa fam phi b -> UnifyM kappa fam phi ()+ record_eq var q = do+ sigma <- get+ case substLkup sigma var of+ -- First time we see 'var', we instantiate it and get going.+ Nothing -> when (not $ eqHO q (Hole var))+ $ modify (\s -> substInsert s var q)+ -- It's not the first time we thin 'var'; previously, we had+ -- that 'var' was supposed to be p'. We will check whether it+ -- is the same as q, if not, we will have to thin p' with q.+ Just q' -> unless (eqHO q' q)+ $ void $ getEquivs q q'+ ++-- |The minimization step performs the /occurs check/ and removes+-- unecessary steps, returning an idempodent substitution when+-- successful. For example;+--+-- > sigma = fromList+-- > [ (0 , bin 1 2)+-- > , (1 , bin 4 4) ]+--+-- Then, @minimize sigma@ will return @fromList [(0 , bin (bin 4 4) 2) , (1 , bin 4 4)]@+-- This returns @Left vs@ if occurs-check fail for variables @vs@.+--+minimize :: forall kappa fam phi . (Ord (Exists phi))+ => Subst kappa fam phi -- ^+ -> Either [Exists phi] (Subst kappa fam phi)+minimize sigma =+ let sigma' = breakCycles inj proj $ removeIds proj sigma+ in whileM sigma' [] $ \s _+ -> M.fromList <$> (mapM (secondF (exMapM (go sigma'))) (M.toList s))+ where+ inj :: Exists phi -> Exists (Holes kappa fam phi)+ inj = exMap Hole++ proj :: Exists (Holes kappa fam phi) -> Maybe (Exists phi)+ proj (Exists (Hole phi)) = Just $ Exists phi+ proj _ = Nothing+ + secondF :: (Functor m) => (a -> m b) -> (x , a) -> m (x , b)+ secondF f (x , a) = (x,) <$> f a++ -- The actual engine of the 'minimize' function is thinning the+ -- variables that appear in the image of the substitution under production.+ -- We use the writer monad solely to let us know whether some variables have+ -- been substituted in this current term. After one iteration+ -- of the map where no variable is further refined, we are done.+ go :: Subst kappa fam phi+ -> Holes kappa fam phi at+ -> Writer [Exists phi] (Holes kappa fam phi at)+ go ss = holesRefineHolesM $ \var -> do+ case substLkup ss var of+ Nothing -> return (Hole var)+ Just r -> tell [Exists var]+ >> return r++ -- | Just like nub; but works on a sorted list+ mnub :: (Ord a) => [a] -> [a]+ mnub [] = []+ mnub [x] = [x]+ mnub (x:y:ys)+ | x == y = mnub (y:ys)+ | otherwise = x : mnub (y:ys)++ -- We loop while there is work to be done or no progress+ -- was done.+ whileM :: (Ord (Exists phi))+ => a -> [Exists phi] -> (a -> [Exists phi] -> Writer [Exists phi] a)+ -> Either [Exists phi] a+ whileM a xs f = do+ let (x' , xs') = runWriter (f a xs)+ if null xs'+ then return x'+ else if (mnub (sort xs') == mnub (sort xs))+ then Left xs'+ else whileM x' xs' f++-- |Removes the keys that project to themselves according to+-- the provided projection.+--+-- > removeIds id $ M.fromList [(0,0), (1,2) , (3,4)]+-- > = M.fromList [(1,2),(3,4)]+--+removeIds :: forall a b+ . (Ord a) => (b -> Maybe a) -> M.Map a b -> M.Map a b+removeIds proj = M.filterWithKey (\a b -> not $ Just a == proj b)+++-- |Will make sure there are no cycles in the map as per the+-- provided function. For example,+--+-- > breakCycles id Just $ M.fromList [(0,1) , (1,2) , (2,0)]+-- > = M.fromList [(1,0),(2,0)]+--+-- Usefull when the maps represent some sort of equivalence; the function+-- essentially collapses the equivalence class.+breakCycles :: forall a b+ . (Ord a) => (a -> b) -> (b -> Maybe a) -> M.Map a b -> M.Map a b+breakCycles inj proj m0+ = let (flattenedCycles , m') = runState (dropCycles m0) M.empty+ in M.union flattenedCycles m'+ where+ dropCycles :: M.Map a b -> State (M.Map a b) (M.Map a b)+ dropCycles m = case findCycle m of+ Nothing -> return m+ Just (a , cyc) -> do+ modify (M.union cyc)+ dropCycles (M.delete a (m M.\\ cyc))++ cycleFor :: a -> M.Map a b -> Maybe (M.Map a b)+ cycleFor a0 m = M.lookup a0 m >>= proj >>= go M.empty+ where+ go :: M.Map a b -> a -> Maybe (M.Map a b)+ go aux a'+ | a' == a0 || a' `M.member` aux = return aux+ | otherwise = M.lookup a' m >>= proj >>= go (M.insert a' (inj a0) aux) ++ findCycle :: M.Map a b -> Maybe (a , M.Map a b)+ findCycle m = (`runCont` id) $ callCC $+ \exit -> (>> return Nothing) . flip mapM_ (M.keys m) $+ \a -> case cycleFor a m of+ Nothing -> return ()+ Just r -> exit $ Just (a , r)
+ src/Generics/Simplistic/Util.hs view
@@ -0,0 +1,249 @@+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE PatternSynonyms #-}+module Generics.Simplistic.Util+ ( -- * Utility Functions and Types+ (&&&) , (***) , (:->) , (<.>)+ -- * Poly-kind indexed product functionality+ , (:*:)(..) , Delta , curry' , uncurry' , delta , deltaMap+ -- * Poly-kind indexed sums+ , Sum(..) , either' , either''+ -- * Constraints+ , Implies , Trivial+ -- * Higher-order Eq and Show+ , EqHO(..) , ShowHO(..)+ -- * Existential Wrapper+ , Exists(..) , exMap , exMapM , exElim+ -- * Elem functionality+ , Elem , NotElem , HasElem(..) , ElemPrf(..) , IsElem, sameTy+ -- * Witnessing and All constraints+ , All , Witness(..) , witness , witnessPrf+ , weq , wshow+ ) where++import Data.Kind (Constraint)+import Data.Proxy (Proxy(..))+import Data.Functor.Sum+import Data.Functor.Const+import Data.Type.Equality+import Control.Arrow ((***) , (&&&))+import GHC.Generics ((:*:)(..), V1 , U1(..))++-- |Lifted curry+curry' :: ((f :*: g) x -> a) -> f x -> g x -> a+curry' f fx gx = f (fx :*: gx)++-- |Lifted uncurry+uncurry' :: (f x -> g x -> a) -> (f :*: g) x -> a+uncurry' f (fx :*: gx) = f fx gx++-- |Natural transformations+type f :-> g = forall n . f n -> g n++-- |Diagonal indexed functor+type Delta f = f :*: f++-- |Duplicates its argument+delta :: f :-> Delta f+delta fx = fx :*: fx++-- |Applies the same function to both components of the pair+deltaMap :: (f :-> g) -> Delta f :-> Delta g+deltaMap f (x :*: y) = f x :*: f y++-- |Higher-order sum eliminator+either' :: (f :-> r) -> (g :-> r) -> Sum f g :-> r+either' f _ (InL x) = f x+either' _ g (InR x) = g x++-- |Just like 'either'', but the result type is of kind Star+either'' :: (forall x . f x -> a) -> (forall y . g y -> a) -> Sum f g r -> a+either'' f g = getConst . either' (Const . f) (Const . g)++infixr 8 <.>+-- |Kleisli Composition+(<.>) :: (Monad m) => (b -> m c) -> (a -> m b) -> a -> m c+f <.> g = (>>= f) . g++-- |Constraint implication+class (c => d) => Implies c d+instance (c => d) => Implies c d++-- |Trivial constraint+class Trivial c+instance Trivial c++-- |Higher order , poly kinded, version of 'Eq'+class EqHO (f :: ki -> *) where+ eqHO :: forall k . f k -> f k -> Bool++instance Eq a => EqHO (Const a) where+ eqHO (Const a) (Const b) = a == b++instance (EqHO f, EqHO g) => EqHO (f :*: g) where+ eqHO (fx :*: gx) (fy :*: gy) = eqHO fx fy && eqHO gx gy++instance (EqHO f, EqHO g) => EqHO (Sum f g) where+ eqHO (InL fx) (InL fy) = eqHO fx fy+ eqHO (InR gx) (InR gy) = eqHO gx gy+ eqHO _ _ = False++instance EqHO V1 where+ eqHO _ _ = True++instance EqHO U1 where+ eqHO _ _ = True++++-- |Higher order, poly kinded, version of 'Show'; We provide+-- the same 'showsPrec' mechanism. The documentation of "Text.Show"+-- has a good example of the correct usage of 'showsPrec':+--+-- > +-- > infixr 5 :^:+-- > data Tree a = Leaf a | Tree a :^: Tree a+-- >+-- > instance (Show a) => Show (Tree a) where+-- > showsPrec d (Leaf m) = showParen (d > app_prec) $+-- > showString "Leaf " . showsPrec (app_prec+1) m+-- > where app_prec = 10+-- > +-- > showsPrec d (u :^: v) = showParen (d > up_prec) $+-- > showsPrec (up_prec+1) u .+-- > showString " :^: " .+-- > showsPrec (up_prec+1) v+-- > where up_prec = 5+--+class ShowHO (f :: ki -> *) where+ showHO :: forall k . f k -> String+ showsPrecHO :: forall k . Int -> f k -> ShowS+ {-# MINIMAL showHO | showsPrecHO #-}++ showHO fx = showsPrecHO 0 fx ""+ showsPrecHO _ fx s = showHO fx ++ s++instance Show a => ShowHO (Const a) where+ showsPrecHO d (Const a) = showParen (d > app_prec) $+ showString "Const " . showsPrec (app_prec + 1) a+ where app_prec = 10++instance (ShowHO f , ShowHO g) => ShowHO (f :*: g) where+ showsPrecHO d (x :*: y) = showParen (d > app_prec) $+ showsPrecHO (app_prec+1) x+ . showString " :*: "+ . showsPrecHO (app_prec+1) y+ where app_prec = 10++instance (ShowHO f , ShowHO g) => ShowHO (Sum f g) where+ showsPrecHO d (InL fx) = showParen (d > app_prec) $+ showString "InL " . showsPrecHO (app_prec + 1) fx+ where app_prec = 10+ showsPrecHO d (InR gx) = showParen (d > app_prec) $+ showString "InR " . showsPrecHO (app_prec + 1) gx+ where app_prec = 10++-- |Existential type wrapper. This comesin particularly+-- handy when we want to add mrsop terms to+-- some container. See "Generics.MRSOP.Holes.Unify" for example.+data Exists (f :: k -> *) :: * where+ Exists :: f x -> Exists f++-- |Maps over 'Exists'+exMap :: (forall x . f x -> g x) -> Exists f -> Exists g+exMap f (Exists x) = Exists (f x)++-- |Maps a monadic actino over 'Exists'+exMapM :: (Monad m) => (forall x . f x -> m (g x)) -> Exists f -> m (Exists g)+exMapM f (Exists x) = Exists <$> f x++-- |eliminates an 'Exists'+exElim :: (forall x . f x -> a) -> Exists f -> a+exElim f (Exists x) = f x++instance ShowHO f => Show (Exists f) where+ show = exElim showHO++-- Boolean predicate about being element of a list+type family IsElem (a :: k) (as :: [ k ]) :: Bool where+ IsElem a (a ': as) = 'True+ IsElem a (b ': as) = IsElem a as+ IsElem a '[] = 'False++-- An actual proof that something is an element+data ElemPrf a as where+ Here :: ElemPrf a (a ': as)+ There :: ElemPrf a as -> ElemPrf a (b ': as)++-- Constructing these proofs+class HasElem a as where+ hasElem :: ElemPrf a as+instance {-# OVERLAPPING #-} HasElem a (a ': as) where+ hasElem = Here+instance {-# OVERLAPPABLE #-}+ (HasElem a as) => HasElem a (b ': as) where+ hasElem = There hasElem++-- |We will carry constructive information on the+-- constraint. Forcing 'IsElem' to true +type Elem a as = (IsElem a as ~ 'True , HasElem a as)++-- |Negation of 'Elem'+type NotElem a as = IsElem a as ~ 'False++-- |Returns whether two types are the same, given that+-- both belong to the same list.+sameTy :: forall fam x y . (Elem x fam , Elem y fam) + => Proxy fam -> Proxy x -> Proxy y -> Maybe (x :~: y)+sameTy _ _ _ = go (hasElem :: ElemPrf x fam) (hasElem :: ElemPrf y fam)+ where+ go :: ElemPrf x fam' -> ElemPrf b fam' -> Maybe (x :~: b)+ go Here Here = Just Refl+ go (There rr) (There y) = go rr y+ go _ _ = Nothing++type family All (c :: k -> Constraint) (xs :: [k]) :: Constraint where+ All c '[] = ()+ All c (x ': xs) = (c x , All c xs)++-- |Carries information about @x@ being an instance of @c@+data Witness c x where+ Witness :: (c x) => Witness c x++-- |Provides the witness that @x@ is an instance of @c@+witness :: forall x xs c+ . (HasElem x xs , All c xs)+ => Proxy xs -> Witness c x+witness _ = witnessPrf (hasElem :: ElemPrf x xs)++-- |Fetches the 'Eq' instance for an element of a list+weq :: forall x xs+ . (All Eq xs , Elem x xs)+ => Proxy xs -> x -> x -> Bool+weq p = case witness p :: Witness Eq x of+ Witness -> (==)++-- |Fetches the 'Eq' instance for an element of a list+wshow :: forall x xs+ . (All Show xs , Elem x xs)+ => Proxy xs -> x -> String+wshow p = case witness p :: Witness Show x of+ Witness -> show++-- |Provides the witness that @x@ is an instance of @c@+witnessPrf :: (All c xs) => ElemPrf x xs -> Witness c x+witnessPrf Here = Witness+witnessPrf (There p) = witnessPrf p+
+ src/Generics/Simplistic/Zipper.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- |Provides bare-bones /zipper/ functionality+-- to 'SRep' and 'Holes'.+module Generics.Simplistic.Zipper where++import Data.Proxy+import Data.Type.Equality+import GHC.Generics+import Data.Functor.Sum+import Control.Arrow (first)++import Generics.Simplistic+import Generics.Simplistic.Deep+import Generics.Simplistic.Util++-- |A value of type 'SZip ty w f' corresponds to a value of type+-- 'SRep w f' with one of its leaves of type @w ty@ absent.+-- This is essentially a zipper for 'SRep'.+data SZip ty w f where+ Z_KH :: SZip ty w (K1 i ty)++ Z_L1 :: SZip ty w f -> SZip ty w (f :+: g)+ Z_R1 :: SZip ty w g -> SZip ty w (f :+: g)+ Z_PairL :: SZip ty w f -> SRep w g -> SZip ty w (f :*: g)+ Z_PairR :: SRep w f -> SZip ty w g -> SZip ty w (f :*: g)+ Z_M1 :: SMeta i t -> SZip ty w f -> SZip ty w (M1 i t f)+deriving instance (forall a. Show (w a)) => Show (SZip h w f)+deriving instance (forall a. Eq (w a)) => Eq (SZip h w f)++-- |We can transform a 'SZip' into a 'SRep' given+-- we are provided with a value to /plug/ into the identified position.+plug :: SZip ty phi f -> phi ty -> SRep phi f+plug Z_KH k = S_K1 k+plug (Z_L1 x) k = S_L1 $ plug x k+plug (Z_R1 x) k = S_R1 $ plug x k+plug (Z_M1 c x) k = S_M1 c $ plug x k+plug (Z_PairL x y) k = (plug x k) :**: y+plug (Z_PairR x y) k = x :**: (plug y k)++-- |Maps over a 'SZip'+zipperMap :: (forall x . h x -> g x)+ -> SZip ty h f -> SZip ty g f+zipperMap f (Z_L1 x) = Z_L1 (zipperMap f x)+zipperMap f (Z_R1 x) = Z_R1 (zipperMap f x)+zipperMap f (Z_M1 c x) = Z_M1 c (zipperMap f x)+zipperMap f (Z_PairL x y) = Z_PairL (zipperMap f x) (repMap f y)+zipperMap f (Z_PairR x y) = Z_PairR (repMap f x) (zipperMap f y)+zipperMap _ Z_KH = Z_KH++inr1 :: (x :*: y) t -> (Sum z x :*: y) t+inr1 (x :*: y) = (InR x :*: y)++-- |Given a @z :: SZip ty h f@ and a @r :: Rep w f@, if @z@ and @r@+-- are made with the same constuctor we return a representation+-- that contains both @h@s and @w@s in its leaves, except in one leaf+-- of type @ty@. This is analogous to 'zipSRep'.+zipperRepZip :: SZip ty h f -> SRep w f -> Maybe (SRep ((Sum ((:~:) ty) h) :*: w) f)+zipperRepZip Z_KH (S_K1 y) = return $ S_K1 (InL Refl :*: y)+zipperRepZip (Z_L1 x) (S_L1 y) = S_L1 <$> zipperRepZip x y+zipperRepZip (Z_R1 x) (S_R1 y) = S_R1 <$> zipperRepZip x y+zipperRepZip (Z_M1 c x) (S_M1 _ y) = S_M1 c <$> zipperRepZip x y+zipperRepZip (Z_PairL x y) (y1 :**: y2)+ = (:**:) <$> zipperRepZip x y1 <*> (repMap inr1 <$> zipSRep y y2)+zipperRepZip (Z_PairR x y) (y1 :**: y2)+ = (:**:) <$> (repMap inr1 <$> zipSRep x y1) <*> zipperRepZip y y2+zipperRepZip _ _ = Nothing++-- |Overlaps two zippers together; only succeeds if both zippers+-- have the same constructor AND hole.+zipSZip :: SZip ty h f -> SZip ty w f -> Maybe (SZip ty (h :*: w) f)+zipSZip Z_KH Z_KH = Just Z_KH+zipSZip (Z_L1 x) (Z_L1 y) = Z_L1 <$> zipSZip x y+zipSZip (Z_R1 x) (Z_R1 y) = Z_R1 <$> zipSZip x y+zipSZip (Z_M1 c x) (Z_M1 _ y) = Z_M1 c <$> zipSZip x y+zipSZip (Z_PairL x y) (Z_PairL w z)+ = Z_PairL <$> zipSZip x w <*> zipSRep y z+zipSZip (Z_PairR x y) (Z_PairR w z)+ = Z_PairR <$> zipSRep x w <*> zipSZip y z+zipSZip _ _ = Nothing++-- |Analogous to 'repLeavesList'+zipLeavesList :: SZip ty w f -> [Maybe (Exists w)]+zipLeavesList (Z_L1 x) = zipLeavesList x+zipLeavesList (Z_R1 x) = zipLeavesList x+zipLeavesList (Z_M1 _ x) = zipLeavesList x+zipLeavesList (Z_PairL l x) = zipLeavesList l ++ map Just (repLeavesList x)+zipLeavesList (Z_PairR x l) = map Just (repLeavesList x) ++ zipLeavesList l+zipLeavesList (Z_KH ) = [Nothing]++-- |The 'Zipper' datatype packages a 'SZip' in a more standard+-- presentation. A value of type @Zipper c f g t@ represents+-- a value of type @SRep f t@, where exactly one recursive leaf (of type @t@)+-- carries a value of type @g t@, moreover, we also carry a proof that+-- the constraint @c@ holds.+data Zipper c f g t where+ Zipper :: c+ => { zipper :: SZip t f (Rep t)+ , sel :: g t+ }+ -> Zipper c f g t++-- |Auxiliar type synonym for annotated fixpoints.+type Zipper' kappa fam ann phi t+ = Zipper (CompoundCnstr kappa fam t)+ (HolesAnn kappa fam ann phi)+ (HolesAnn kappa fam ann phi) t++-- |Given a function that checks wheter an arbitrary position+-- is recursive and a value of @t@, returns all possible zippers ove+-- @t@. +zippers :: forall kappa fam ann phi t+ . (forall a . (Elem t fam) => phi a -> Maybe (a :~: t)) + -> HolesAnn kappa fam ann phi t+ -> [Zipper' kappa fam ann phi t] +zippers _ (Prim' _ _) = []+zippers _ (Hole' _ _) = []+zippers aux (Roll' _ r) = map (uncurry Zipper) (go r)+ where+ pf :: Proxy fam+ pf = Proxy++ pa :: HolesAnn kappa fam ann phi a -> Proxy a+ pa _ = Proxy++ go :: SRep (HolesAnn kappa fam ann phi) f+ -> [(SZip t (HolesAnn kappa fam ann phi) f+ , HolesAnn kappa fam ann phi t)]+ go S_U1 = []+ go (S_L1 x) = first Z_L1 <$> go x+ go (S_R1 x) = first Z_R1 <$> go x+ go (S_M1 c x) = first (Z_M1 c) <$> go x+ go (x :**: y) = (first (flip Z_PairL y) <$> go x)+ ++ (first (Z_PairR x) <$> go y)+ go (S_K1 x@(Roll' _ _)) =+ case sameTy pf (Proxy :: Proxy t) (pa x) of+ Just Refl -> return $ (Z_KH , x)+ Nothing -> []+ go (S_K1 x@(Hole' _ xh)) = + case aux xh of+ Just Refl -> return $ (Z_KH , x)+ Nothing -> []+ go _ = []+ +-- |Retrieves the constructor name for a representation.+-- /WARNING; UNSAFE/ this function only works if @f@ is the representation of+-- a type constructed with "GHC.Generics" builtin mechanisms.+zipConstructorName :: SZip h w f -> String+zipConstructorName (Z_M1 x@SM_C _)+ = getConstructorName x+zipConstructorName (Z_M1 _ x)+ = zipConstructorName x+zipConstructorName (Z_L1 x)+ = zipConstructorName x+zipConstructorName (Z_R1 x)+ = zipConstructorName x+zipConstructorName _+ = error "Please; use GHC's deriving mechanism. This keeps M1's at the top of the Rep"+