packages feed

generic-lens 0.5.0.0 → 0.5.1.0

raw patch · 10 files changed

+289/−69 lines, 10 filesdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base

API changes (from Hackage documentation)

- Data.Generics.Product.Fields: instance (GHC.Generics.Generic s, Data.Generics.Product.Fields.ErrorUnless field s (Data.Generics.Internal.Families.Collect.CollectField field (GHC.Generics.Rep s)), GHC.Generics.Generic t, s' ~ Data.Generics.Internal.Families.Changing.Proxied s, GHC.Generics.Generic s', Data.Generics.Product.Internal.Fields.GHasField' field (GHC.Generics.Rep s) a, Data.Generics.Product.Internal.Fields.GHasField' field (GHC.Generics.Rep s') a', Data.Generics.Product.Internal.Fields.GHasField field (GHC.Generics.Rep s) (GHC.Generics.Rep t) a b, '(t, b) ~ Data.Generics.Internal.Families.Changing.Infer s' a' a (Data.Generics.Internal.Families.Changing.PickTv a' b)) => Data.Generics.Product.Fields.HasField field s t a b
- Data.Generics.Product.Fields: instance Data.Generics.Product.Fields.HasField f (Data.Generics.Internal.Void.Void2 t a) t a b
- Data.Generics.Product.Positions: instance (GHC.Generics.Generic s, Data.Generics.Product.Positions.ErrorUnless i s ((0 Data.Generics.Product.Internal.Positions.<? i) Data.Type.Bool.&& (i GHC.TypeNats.<=? Data.Generics.Product.Internal.Positions.Size (GHC.Generics.Rep s))), GHC.Generics.Generic t, s' ~ Data.Generics.Internal.Families.Changing.Proxied s, Data.Generics.Product.Internal.Positions.GHasPosition' i (GHC.Generics.Rep s) a, Data.Generics.Product.Internal.Positions.GHasPosition' i (GHC.Generics.Rep s') a', Data.Generics.Product.Internal.Positions.GHasPosition 1 i (GHC.Generics.Rep s) (GHC.Generics.Rep t) a b, '(t, b) ~ Data.Generics.Internal.Families.Changing.Infer s' a' a (Data.Generics.Internal.Families.Changing.PickTv a' b)) => Data.Generics.Product.Positions.HasPosition i s t a b
- Data.Generics.Product.Positions: instance Data.Generics.Product.Positions.HasPosition f (Data.Generics.Internal.Void.Void2 a t) t a b
- Data.Generics.Sum.Constructors: instance (GHC.Generics.Generic s, Data.Generics.Sum.Constructors.ErrorUnless ctor s (Data.Generics.Internal.Families.Has.HasCtorP ctor (GHC.Generics.Rep s)), GHC.Generics.Generic t, s' ~ Data.Generics.Internal.Families.Changing.Proxied s, GHC.Generics.Generic s', Data.Generics.Sum.Internal.Constructors.GAsConstructor' ctor (GHC.Generics.Rep s) a, Data.Generics.Sum.Internal.Constructors.GAsConstructor' ctor (GHC.Generics.Rep s') a', Data.Generics.Sum.Internal.Constructors.GAsConstructor ctor (GHC.Generics.Rep s) (GHC.Generics.Rep t) a b, '(t, b) ~ Data.Generics.Internal.Families.Changing.Infer s' a' a (Data.Generics.Internal.Families.Changing.PickTv a' b)) => Data.Generics.Sum.Constructors.AsConstructor ctor s t a b
+ Data.Generics.Product.Fields: instance (GHC.Generics.Generic s, Data.Generics.Product.Fields.ErrorUnless field s (Data.Generics.Internal.Families.Collect.CollectField field (GHC.Generics.Rep s)), GHC.Generics.Generic t, s' ~ Data.Generics.Internal.Families.Changing.Proxied s, t' ~ Data.Generics.Internal.Families.Changing.Proxied t, GHC.Generics.Generic s', GHC.Generics.Generic t', Data.Generics.Product.Internal.Fields.GHasField' field (GHC.Generics.Rep s) a, Data.Generics.Product.Internal.Fields.GHasField' field (GHC.Generics.Rep s') a', Data.Generics.Product.Internal.Fields.GHasField' field (GHC.Generics.Rep t') b', Data.Generics.Product.Internal.Fields.GHasField field (GHC.Generics.Rep s) (GHC.Generics.Rep t) a b, t ~ Data.Generics.Internal.Families.Changing.Infer s a' b, s ~ Data.Generics.Internal.Families.Changing.Infer t b' a) => Data.Generics.Product.Fields.HasField field s t a b
+ Data.Generics.Product.Positions: instance (GHC.Generics.Generic s, Data.Generics.Product.Positions.ErrorUnless i s ((0 Data.Generics.Product.Internal.Positions.<? i) Data.Type.Bool.&& (i GHC.TypeNats.<=? Data.Generics.Product.Internal.Positions.Size (GHC.Generics.Rep s))), GHC.Generics.Generic t, s' ~ Data.Generics.Internal.Families.Changing.Proxied s, t' ~ Data.Generics.Internal.Families.Changing.Proxied t, GHC.Generics.Generic s', GHC.Generics.Generic t', Data.Generics.Product.Internal.Positions.GHasPosition' i (GHC.Generics.Rep s) a, Data.Generics.Product.Internal.Positions.GHasPosition' i (GHC.Generics.Rep s') a', Data.Generics.Product.Internal.Positions.GHasPosition 1 i (GHC.Generics.Rep s) (GHC.Generics.Rep t) a b, t ~ Data.Generics.Internal.Families.Changing.Infer s a' b, Data.Generics.Product.Internal.Positions.GHasPosition' i (GHC.Generics.Rep t') b', s ~ Data.Generics.Internal.Families.Changing.Infer t b' a) => Data.Generics.Product.Positions.HasPosition i s t a b
+ Data.Generics.Product.Positions: instance Data.Generics.Product.Positions.HasPosition f (Data.Generics.Internal.Void.Void1 a) (Data.Generics.Internal.Void.Void1 b) a b
+ Data.Generics.Sum.Constructors: instance (GHC.Generics.Generic s, Data.Generics.Sum.Constructors.ErrorUnless ctor s (Data.Generics.Internal.Families.Has.HasCtorP ctor (GHC.Generics.Rep s)), GHC.Generics.Generic t, s' ~ Data.Generics.Internal.Families.Changing.Proxied s, t' ~ Data.Generics.Internal.Families.Changing.Proxied t, GHC.Generics.Generic s', GHC.Generics.Generic t', Data.Generics.Sum.Internal.Constructors.GAsConstructor' ctor (GHC.Generics.Rep s) a, Data.Generics.Sum.Internal.Constructors.GAsConstructor' ctor (GHC.Generics.Rep s') a', Data.Generics.Sum.Internal.Constructors.GAsConstructor ctor (GHC.Generics.Rep s) (GHC.Generics.Rep t) a b, t ~ Data.Generics.Internal.Families.Changing.Infer s a' b, Data.Generics.Sum.Internal.Constructors.GAsConstructor' ctor (GHC.Generics.Rep t') b', s ~ Data.Generics.Internal.Families.Changing.Infer t b' a) => Data.Generics.Sum.Constructors.AsConstructor ctor s t a b
- Data.Generics.Product.Fields: class HasField (field :: Symbol) s t a b | s field -> a, s field b -> t
+ Data.Generics.Product.Fields: class HasField (field :: Symbol) s t a b | s field -> a, s field b -> t, t field a -> s
- Data.Generics.Product.Positions: class HasPosition (i :: Nat) s t a b | s i -> a, s i b -> t
+ Data.Generics.Product.Positions: class HasPosition (i :: Nat) s t a b | s i -> a, s i b -> t, t i a -> s

Files

ChangeLog.md view
@@ -1,3 +1,9 @@+## 0.5.1.0+- Infer input type from result type (#25)+- Allow changing of multiple type parameters (#24)+- Allow changing of type parameters that have kinds other than `*` (#23)+- Fix error message in subtype lens+ ## 0.5.0.0  - Lenses and prisms are now type-changing.
examples/Examples.hs view
@@ -1,17 +1,18 @@-{-# LANGUAGE AllowAmbiguousTypes         #-}-{-# LANGUAGE DataKinds                   #-}-{-# LANGUAGE DeriveGeneric               #-}-{-# LANGUAGE DuplicateRecordFields       #-}-{-# LANGUAGE FlexibleContexts            #-}-{-# LANGUAGE GADTs                       #-}-{-# LANGUAGE NoMonomorphismRestriction   #-}-{-# LANGUAGE PartialTypeSignatures       #-}-{-# LANGUAGE Rank2Types                  #-}-{-# LANGUAGE ScopedTypeVariables         #-}-{-# LANGUAGE TypeApplications            #-}-{-# LANGUAGE UndecidableInstances        #-}-{-# OPTIONS_GHC -Wno-missing-signatures  #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}+{-# LANGUAGE AllowAmbiguousTypes          #-}+{-# LANGUAGE DataKinds                    #-}+{-# LANGUAGE DeriveGeneric                #-}+{-# LANGUAGE DuplicateRecordFields        #-}+{-# LANGUAGE FlexibleContexts             #-}+{-# LANGUAGE GADTs                        #-}+{-# LANGUAGE NoMonomorphismRestriction    #-}+{-# LANGUAGE OverloadedLabels             #-}+{-# LANGUAGE PartialTypeSignatures        #-}+{-# LANGUAGE Rank2Types                   #-}+{-# LANGUAGE ScopedTypeVariables          #-}+{-# LANGUAGE TypeApplications             #-}+{-# LANGUAGE UndecidableInstances         #-}+{-# OPTIONS_GHC -Wno-missing-signatures   #-}+{-# OPTIONS_GHC -fno-warn-unused-imports  #-}  module Examples where @@ -20,6 +21,7 @@ import Data.Generics.Product import Data.Generics.Sum import GHC.Generics+import Data.Generics.Labels  data Animal = Animal   { name :: String@@ -102,3 +104,24 @@   , HasField "bar" a' b' s t   ) => s' -> t' stuff r = r & field @"test" . field @"bar" . position @15 .~ "hello"++stuff' ::+  ( HasPosition 15 s t a String+  , HasField "test" s' t' a' b'+  , HasField "bar" a' b' s t+  ) => s' -> t'+stuff' r = r & #test . #bar . position @15 .~ "hello"++data Foo m s = Foo+  { foo1 :: m s+  , foo2 :: [s]+  } deriving Generic++modifyFoo2 :: Foo (Either String) Int -> Foo Maybe Int+modifyFoo2 x = x & field @"foo1" .~ pure (1 :: Int)++data Bar a b = Bar+  { barField :: (a, b)+  } deriving Generic++modifiedBar = (Bar ("hello", "world")) & field @"barField" .~ ('c', 1 :: Int)
generic-lens.cabal view
@@ -1,5 +1,5 @@ name:                 generic-lens-version:              0.5.0.0+version:              0.5.1.0 synopsis:             Generic data-structure operations exposed as lenses. description:          This package uses the GHC 8 Generic representation to derive various operations on data structures with a lens interface, including structural subtype relationship between records and positional indexing into arbitrary product types. @@ -25,6 +25,7 @@                     , Data.Generics.Product.Positions                     , Data.Generics.Product.Subtype                     , Data.Generics.Product.Typed+                    --, Data.Generics.Labels                      , Data.Generics.Sum                     , Data.Generics.Sum.Any@@ -69,6 +70,30 @@   build-depends:      base          >= 4.9 && <= 5.0                     , generic-lens                     , inspection-testing >= 0.1++  default-language:   Haskell2010+  ghc-options:        -Wall++test-suite generic-lens-test-25+  type:               exitcode-stdio-1.0+  hs-source-dirs:     test+  main-is:            25.hs++  build-depends:      base          >= 4.9 && <= 5.0+                    , generic-lens+                    , lens++  default-language:   Haskell2010+  ghc-options:        -Wall++test-suite generic-lens-test-24+  type:               exitcode-stdio-1.0+  hs-source-dirs:     test+  main-is:            24.hs++  build-depends:      base          >= 4.9 && <= 5.0+                    , generic-lens+                    , lens    default-language:   Haskell2010   ghc-options:        -Wall
src/Data/Generics/Internal/Families/Changing.hs view
@@ -2,14 +2,19 @@ {-# LANGUAGE DataKinds              #-} {-# LANGUAGE FlexibleInstances      #-} {-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GADTs                  #-} {-# LANGUAGE PolyKinds              #-} {-# LANGUAGE TypeFamilies           #-} {-# LANGUAGE TypeOperators          #-} {-# LANGUAGE UndecidableInstances   #-} -module Data.Generics.Internal.Families.Changing where+module Data.Generics.Internal.Families.Changing+  ( Proxied+  , Infer+  ) where -import GHC.TypeLits (Nat, type (+))+import GHC.TypeLits (TypeError, ErrorMessage (..))+import Data.Type.Bool (If)  {-   Note [Changing type parameters]@@ -35,53 +40,106 @@   If after doing the conversion on @s@, @field@'s type is @(P _ a), then @t@ is   @s[b/a]@, otherwise @t ~ s@ and @b ~ a@. -}-data P (i :: Nat) a -type Proxied t = Proxied' t 0+-- `P` can be used in place of any type parameter, which means that it can have+-- any kind, not just *, so a data type won't work.+-- (this caused https://github.com/kcsongor/generic-lens/issues/23)+-- Instead, we use a matchable type family to wrap any `k` - however, we can no longer directly+-- pattern match on `P`, as it's not a type constructor. But we can still take it apart as a polymorphic+-- application form. In order to distinguish between applications of P and other type constructors, we use a tag, `PTag`+-- to fake a type constructor.+data PTag = PTag+type family P :: Peano -> k -> PTag -> k -type family Proxied' (t :: k) (next :: Nat) :: k where-  Proxied' (t a :: k) next = (Proxied' t (next + 1)) (P next a)+type Proxied t = Proxied' t 'Z++type family Proxied' (t :: k) (next :: Peano) :: k where+  Proxied' (t (a :: j) :: k) next = (Proxied' t ('S next)) (P next a 'PTag)   Proxied' t _ = t -type family UnProxied (t :: k) :: k where-  UnProxied (P _ a) = a-  UnProxied (t (P _ a) :: k) = UnProxied t a-  UnProxied t = t+data Sub where+  Sub :: Peano -> k -> Sub -type family Change (t :: k) (target :: Nat) (to :: j) :: k where-  Change (P target _) target to = (P target to)-  Change (t (P target _) :: k) target to = t (P target to)-  Change (t a :: k) target to = Change t target to a-  Change t _ _ = t+type family Unify (a :: k) (b :: k) :: [Sub] where+  Unify (a b) a' = If (IsPTag b) '[HandleP (a b) a'] (HandleOther (a b) a')+  Unify a a = '[]+  Unify a b = TypeError+                ( 'Text "Couldn't match type "+                  ':<>: 'ShowType a+                  ':<>: 'Text " with "+                  ':<>: 'ShowType b+                ) -type family UnApply (a :: k) :: [*] where-  UnApply (f x) = x ': UnApply f-  UnApply x     = '[]+type family HandleP a b where+  HandleP (p n _ 'PTag) a' = 'Sub n a' -type family Unify a b :: [(*, *)] where-  Unify (P n a') a = '[ '(P n a', a)]-  Unify a b = Zip (UnApply a) (UnApply b)+type family HandleOther a b where+  HandleOther (a x) (b y) = Unify x y ++ Unify a b+  HandleOther a a = '[]+  HandleOther a b = TypeError+                     ( 'Text "Couldn't match type "+                       ':<>: 'ShowType a+                       ':<>: 'Text " with "+                       ':<>: 'ShowType b+                     ) -type family PSub (subs :: [(*, *)]) :: [(Nat, *)] where-  PSub '[] = '[]-  PSub ('(P n _, b) ': xs) = '(n, b) ': PSub xs-  PSub (_ ': xs) = PSub xs+type family IsPTag (a :: k) :: Bool where+  IsPTag 'PTag = 'True+  IsPTag _ = 'False -type family Zip (xs :: [k]) (ys :: [l]) :: [(k, l)] where-  Zip '[] '[] = '[]-  Zip (x ': xs) (y ': ys) = '(x, y) ': Zip xs ys+type family (xs :: [k]) ++ (ys :: [k]) :: [k] where+  '[] ++ ys = ys+  (x ': xs) ++ ys = x ': (xs ++ ys) -type family Infer (s :: *) (a' :: *) (a :: *) (w :: *) :: (*, *) where-  Infer s' a' a w-    = Infer' s' a' (PSub (Unify a' a)) w+type family Infer (s :: *) (a' :: *) (b :: *) :: * where+  Infer (s a) a' b+    = ReplaceArgs (s a) (Unify a' b)+  Infer s _ _ = s -type family Infer' (s :: *) (a' :: *) (subs :: [(Nat, k)]) w :: (*, *) where-  Infer' s' a' '[ '(p, _)] w-    = '(UnProxied (Change s' p w), UnProxied (Change a' p w))-  Infer' s' a' _ _-    = '(UnProxied s', UnProxied a')+-------------------------------------------------------------------------------- -type family PickTv (a :: k) (b :: k) :: * where-  PickTv (P _ _) b = b-  PickTv (f (P _ _)) (g b) = b-  PickTv (f a) (g b) = PickTv f g+data Peano = Z | S Peano++-- [TODO]: work this out+--+--type family ArgKind (t :: k) (pos :: Peano) :: * where+--  ArgKind (t (a :: k)) 'Z = k+--  ArgKind (t _) ('S pos) = ArgKind t pos+--+--type family ReplaceArg (t :: k) (pos :: Peano) (to :: ArgKind t pos) :: k where+--  ReplaceArg (t a) 'Z to = t to+--  ReplaceArg (t a) ('S pos) to = ReplaceArg t pos to a+--  ReplaceArg t _ _ = t++type family ReplaceArg (t :: k) (pos :: Peano) (to :: j) :: k where+  ReplaceArg (t a) 'Z to = t to+  ReplaceArg (t a) ('S pos) to = ReplaceArg t pos to a+  ReplaceArg t _ _ = t++type family ReplaceArgs (t :: k) (subs :: [Sub]) :: k where+  ReplaceArgs t '[] = t+  ReplaceArgs t ('Sub n arg ': ss) = ReplaceArgs (ReplaceArg t n arg) ss++-- Note [CPP in instance constraints]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+--+-- In GHC 8.0.2, the calculated size of the expressions is too large for the+-- inliner to consider them under the default -funfolding-use-threshold value+-- (60).+--+-- To reduce the size, the constraints+--+-- ```+-- s' ~ Proxied s+-- t' ~ Proxied t+-- ```+--+-- are written as the following single equality:+--+-- ```+-- '(s', t') ~ '(Proxied s, Proxied t)+-- ```+--+-- However, for some reason, this violates the functional dependencies on 8.2.2.+-- Therefore, when using a newer version of the compiler, the original constraints+-- are used, as the expression size is smaller under 8.2.2.
src/Data/Generics/Product/Fields.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE AllowAmbiguousTypes     #-}+{-# LANGUAGE CPP                     #-} {-# LANGUAGE ConstraintKinds         #-} {-# LANGUAGE DataKinds               #-} {-# LANGUAGE FlexibleInstances       #-}@@ -75,7 +76,7 @@ -- :}  -- |Records that have a field with a given name.-class HasField (field :: Symbol) s t a b | s field -> a, s field b -> t where+class HasField (field :: Symbol) s t a b | s field -> a, s field b -> t, t field a -> s where   -- |A lens that focuses on a field with a given name. Compatible with the   --  lens package's 'Control.Lens.Lens' type.   --@@ -127,20 +128,26 @@   ( Generic s   , ErrorUnless field s (CollectField field (Rep s))   , Generic t+  -- see Note [CPP in instance constraints]+#if __GLASGOW_HASKELL__ < 802+  , '(s', t') ~ '(Proxied s, Proxied t)+#else   , s' ~ Proxied s+  , t' ~ Proxied t+#endif   , Generic s'+  , Generic t'   , GHasField' field (Rep s) a   , GHasField' field (Rep s') a'+  , GHasField' field (Rep t') b'   , GHasField field (Rep s) (Rep t) a b-  , '(t, b) ~ Infer s' a' a (PickTv a' b)+  , t ~ Infer s a' b+  , s ~ Infer t b' a   ) => HasField field s t a b where    field f s = ravel (repLens . gfield @field) f s --- See Note [Uncluttering type signatures]-instance {-# OVERLAPPING #-} HasField f (Void2 t a) t a b where-  field = undefined-+-- -- See Note [Uncluttering type signatures] instance {-# OVERLAPPING #-} HasField f (Void1 a) (Void1 b) a b where   field = undefined 
src/Data/Generics/Product/Positions.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE AllowAmbiguousTypes    #-} {-# LANGUAGE ConstraintKinds        #-} {-# LANGUAGE DataKinds              #-}@@ -70,7 +71,7 @@ -- :}  -- |Records that have a field at a given position.-class HasPosition (i :: Nat) s t a b | s i -> a, s i b -> t where+class HasPosition (i :: Nat) s t a b | s i -> a, s i b -> t, t i a -> s where   -- |A lens that focuses on a field at a given position. Compatible with the   --  lens package's 'Control.Lens.Lens' type.   --@@ -99,17 +100,27 @@   ( Generic s   , ErrorUnless i s (0 <? i && i <=? Size (Rep s))   , Generic t+  -- see Note [CPP in instance constraints]+#if __GLASGOW_HASKELL__ < 802+  , '(s', t') ~ '(Proxied s, Proxied t)+#else   , s' ~ Proxied s+  , t' ~ Proxied t+#endif+  , Generic s'+  , Generic t'   , GHasPosition' i (Rep s) a   , GHasPosition' i (Rep s') a'   , GHasPosition 1 i (Rep s) (Rep t) a b-  , '(t, b) ~ Infer s' a' a (PickTv a' b)+  , t ~ Infer s a' b+  , GHasPosition' i (Rep t') b'+  , s ~ Infer t b' a   ) => HasPosition i s t a b where    position f s = ravel (repLens . gposition @1 @i) f s  -- See Note [Uncluttering type signatures]-instance {-# OVERLAPPING #-} HasPosition f (Void2 a t) t a b where+instance {-# OVERLAPPING #-} HasPosition f (Void1 a) (Void1 b) a b where   position = undefined  type family ErrorUnless (i :: Nat) (s :: Type) (hasP :: Bool) :: Constraint where
src/Data/Generics/Product/Subtype.hs view
@@ -91,8 +91,8 @@   --   -- >>> upcast (upcast human :: Animal) :: Human   -- ...-  -- ... The type 'Human' is not a subtype of 'Animal'.-  -- ... The following fields are missing from 'Human':+  -- ... The type 'Animal' is not a subtype of 'Human'.+  -- ... The following fields are missing from 'Animal':   -- ... address   -- ...   upcast :: sub -> sup@@ -123,11 +123,11 @@ instance {-# OVERLAPPING #-} Subtype Void a where   super = undefined -type family ErrorUnless (sub :: Type) (sup :: Type) (diff :: [Symbol]) :: Constraint where+type family ErrorUnless (sup :: Type) (sub :: Type) (diff :: [Symbol]) :: Constraint where   ErrorUnless _ _ '[]     = () -  ErrorUnless sub sup fs+  ErrorUnless sup sub fs     = TypeError         (     'Text "The type '"         ':<>: 'ShowType sub
src/Data/Generics/Sum/Constructors.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE AllowAmbiguousTypes    #-}+{-# LANGUAGE CPP                    #-} {-# LANGUAGE DataKinds              #-} {-# LANGUAGE FlexibleInstances      #-} {-# LANGUAGE FunctionalDependencies #-}@@ -102,12 +103,21 @@   ( Generic s   , ErrorUnless ctor s (HasCtorP ctor (Rep s))   , Generic t+  -- see Note [CPP in instance constraints]+#if __GLASGOW_HASKELL__ < 802+  , '(s', t') ~ '(Proxied s, Proxied t)+#else   , s' ~ Proxied s+  , t' ~ Proxied t+#endif   , Generic s'+  , Generic t'   , GAsConstructor' ctor (Rep s) a   , GAsConstructor' ctor (Rep s') a'   , GAsConstructor ctor (Rep s) (Rep t) a b-  , '(t, b) ~ Infer s' a' a (PickTv a' b)+  , t ~ Infer s a' b+  , GAsConstructor' ctor (Rep t') b'+  , s ~ Infer t b' a   ) => AsConstructor ctor s t a b where    _Ctor = repIso . _GCtor @ctor
+ test/24.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE DataKinds, DeriveGeneric, TypeApplications #-}++module Main where++-- Test case from #24, comments preserved+import Control.Lens+import Data.Generics.Product.Fields+import Data.Generics.Product.Positions+import GHC.Generics++data Foo a b = Foo { x1 :: a, x2 :: b } deriving (Generic, Show)++data Bar a b = Bar { x3 :: Foo a b, x4 :: Int } deriving (Generic, Show)++tup :: ((Int, Char), Int)+tup = ((1, 'a'), 2)+tup2, tup3, tup4 :: ((Char, Char), Int)+tup2 = tup & _1 . _1 %~ toEnum  -- Works.+tup3 = tup & x %~ toEnum  -- Works also with type annotation.+  where x :: Lens ((Int, Char), Int) ((Char, Char), Int) Int Char+        x = _1 . _1+-- Works.+tup4 = tup & position @1 . position @1 %~ toEnum++foo :: Foo Int Char+foo = Foo 1 'a'+foo2, foo3 :: Foo Char Char+foo2 = foo & field @"x1" %~ toEnum  -- Works when there's just one 'field'.+foo3 = foo & position @1 %~ toEnum -- Works when there's just one 'position'.++bar :: Bar Int Char+bar = Bar (Foo 1 'a') 2+bar2, bar3, bar4 :: Bar Char Char+-- Doesn't work, error at first 'field' (Couldn't match type ‘Int’ with ‘Char’ arising from a use of ‘field’).+bar2 = bar & field @"x3" . field @"x1" %~ toEnum+-- Type annotation doesn't help.+bar3 = bar & l %~ toEnum+  where l :: Lens (Bar Int Char) (Bar Char Char) Int Char+        l = field @"x3" . field @"x1"+-- Doesn't work, error at first 'position' (Couldn't match type ‘Int’ with ‘Char’ arising from a use of ‘position’).+bar4 = bar & position @1 . position @1 %~ toEnum+-- Works if we stick to simple Lens' (modify to the same type).+bar5 :: Bar Int Char+bar5 = bar & field @"x3" . field @"x1" %~ (+1)++main :: IO ()+main = print bar5
+ test/25.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# OPTIONS_GHC -Wall #-}++module Main where++import Control.Lens+import Data.Generics.Product+import GHC.Generics++data Record1 = Record1+    { field1 :: Int+    , field2 :: Double+    } deriving (Generic)++class Default a where+    def :: a++instance Default Record1 where+    def = Record1 0 0.0++f :: Record1 -> Int+f r = r ^. field @"field1"++main :: IO ()+main = do+    print $ f def+    print $ f ( field @"field1" .~ 1 $ (def :: Record1))+    print $ f ( field @"field1" .~ 2 $ Record1 0 0.0)+    print $ f ( field @"field1" .~ (1 :: Int) $ def)+    print $ f ( position @1 .~ (1 :: Int) $ def)