@@ -1,9 +1,14 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE FlexibleContexts #-}
1{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE KindSignatures #-}
5{-# LANGUAGE KindSignatures #-}
3{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
4{-# LANGUAGE ScopedTypeVariables #-}
7{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE TypeApplications #-}
8{-# LANGUAGE TypeApplications #-}
9+{-# LANGUAGE TypeFamilies #-}
6{-# LANGUAGE TypeOperators #-}
10{-# LANGUAGE TypeOperators #-}
11+{-# LANGUAGE UndecidableInstances #-}
8module Data.Generics.Product.Typed
13module Data.Generics.Product.Typed
9 ( HasType (..)
14 ( HasType (..)
@@ -15,14 +20,27 @@ import Data.Generics.Internal.Lens
16import Data.Kind (Type)
21import Data.Kind (Type)
17import GHC.Generics
22import GHC.Generics
20class HasType a s where
24class HasType a s where
21 typed :: Lens' s a
25 typed :: Lens' s a
28+ FindType a (Rep s) ~ 'Just a,
29+ CountType a (Rep s) ~ 'One,
34+ typed = repIso . gtyped
23class GHasType (f :: Type -> Type) a where
36class GHasType (f :: Type -> Type) a where
24 gtyped :: Lens' (f x) a
37 gtyped :: Lens' (f x) a
39+instance GProductHasType l r a (FindType a l)
40+ => GHasType (l :*: r) a where
42+ gtyped = gproductTyped @_ @_ @_ @(FindType a l)
26instance (GHasType l a, GHasType r a) => GHasType (l :+: r) a where
44instance (GHasType l a, GHasType r a) => GHasType (l :+: r) a where
27 gtyped = combine (gtyped @l) (gtyped @r)
45 gtyped = combine (gtyped @l) (gtyped @r)
@@ -37,3 +55,12 @@ instance GHasType f a => GHasType (M1 D meta f) a where
38instance GHasType f a => GHasType (M1 C meta f) a where
56instance GHasType f a => GHasType (M1 C meta f) a where
39 gtyped = mIso . gtyped
57 gtyped = mIso . gtyped
59+class GProductHasType l r a (found :: Maybe Type) where
60+ gproductTyped :: Lens' ((l :*: r) x) a
62+instance GHasType l a => GProductHasType l r a ('Just a) where
63+ gproductTyped = first . gtyped
65+instance GHasType r a => GProductHasType l r a 'Nothing where
66+ gproductTyped = second . gtyped