@@ -1,6 +1,15 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE ConstraintKinds #-}
1{-# LANGUAGE DataKinds #-}
3{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE KindSignatures #-}
3{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE PolyKinds #-}
8+{-# LANGUAGE Rank2Types #-}
9+{-# LANGUAGE ScopedTypeVariables #-}
10+{-# LANGUAGE TypeApplications #-}
11+{-# LANGUAGE TypeFamilies #-}
12+{-# LANGUAGE TypeOperators #-}
4{-# LANGUAGE UndecidableInstances #-}
13{-# LANGUAGE UndecidableInstances #-}
6-----------------------------------------------------------------------------
15-----------------------------------------------------------------------------
@@ -21,11 +30,13 @@ module Data.Generics.Product.Types
22 -- $example
31 -- $example
23 HasTypes (..)
32 HasTypes (..)
26import Data.Generics.Product.Internal.Types
36import Data.Generics.Product.Internal.Types
37+import Data.Kind (Constraint)
28−import GHC.Generics (Generic (Rep))
39+import GHC.Generics
29import Data.Generics.Internal.VL.Traversal
40import Data.Generics.Internal.VL.Traversal
30import Data.Generics.Internal.VL.Iso
41import Data.Generics.Internal.VL.Iso
@@ -38,3 +49,59 @@ instance
38 ) => HasTypes a s where
49 ) => HasTypes a s where
39 types = confusing (\f -> (repIso . gtypes) (f :> HNil))
50 types = confusing (\f -> (repIso . gtypes) (f :> HNil))
40 {-# INLINE types #-}
51 {-# INLINE types #-}
53+class HasTypesDeep a s where
54+ typesDeep :: Traversal' s a
57+ ( HasConstraints' ((~) a) s
58+ ) => HasTypesDeep a s where
60+ typesDeep f s = constraints' @((~) a) f s
62+--------------------------------------------------------------------------------
63+type family Primitive a :: Bool where
64+ Primitive Int = 'True
65+ Primitive Char = 'True
66+ Primitive Bool = 'True
68+ -- TODO: more primitives, or perhaps abstract from stop condition
71+-- deep constrained traversals, stopping at primitive types
72+class HasConstraints' (c :: * -> Constraint) s where
73+ constraints' :: forall g.
74+ Applicative g => (forall a. c a => a -> g a) -> s -> g s
76+instance (Generic s, GHasConstraints' c (Rep s)) => HasConstraints' c s where
77+ constraints' f s = to <$> gconstraints' @c f (from s)
79+class GHasConstraints' (c :: * -> Constraint) (f :: * -> *) where
80+ gconstraints' :: forall g x.
81+ Applicative g => (forall a. c a => a -> g a) -> f x -> g (f x)
83+instance (GHasConstraints' c l, GHasConstraints' c r) => GHasConstraints' c (l :*: r) where
84+ gconstraints' f (l :*: r) = (:*:) <$> gconstraints' @c f l <*> gconstraints' @c f r
86+instance (GHasConstraints' c l, GHasConstraints' c r) => GHasConstraints' c (l :+: r) where
87+ gconstraints' f (L1 l) = L1 <$> gconstraints' @c f l
88+ gconstraints' f (R1 r) = R1 <$> gconstraints' @c f r
90+instance GRec c (Primitive a) (K1 R a) => GHasConstraints' c (K1 R a) where
91+ gconstraints' = grec @c @(Primitive a)
93+instance GHasConstraints' c f => GHasConstraints' c (M1 m meta f) where
94+ gconstraints' f (M1 x) = M1 <$> gconstraints' @c f x
96+instance GHasConstraints' c U1 where
97+ gconstraints' _ _ = pure U1
99+class GRec (c :: * -> Constraint) (s :: Bool) (f :: * -> *) where
101+ Applicative g => (forall a. c a => a -> g a) -> f x -> g (f x)
103+instance HasConstraints' c a => GRec c 'False (K1 R a) where
104+ grec f (K1 s) = K1 <$> constraints' @c @a f s
106+instance c a => GRec c 'True (K1 R a) where