module Data.Profunctor.Product (module Data.Profunctor.Product.Newtype, module Data.Profunctor.Product) where import Prelude hiding (id) import Data.Profunctor (Profunctor, dimap, lmap, WrappedArrow) import qualified Data.Profunctor as Profunctor import Data.Functor.Contravariant (Contravariant, contramap) -- vv TODO: don't want to have to import all those explicitly. What to do? import Data.Profunctor.Product.Flatten -- vv and these import Data.Profunctor.Product.Tuples import Control.Category (id) import Control.Arrow (Arrow, (***), (<<<), arr, (&&&)) import Control.Applicative (Applicative, liftA2, pure) import Data.Monoid (Monoid, mempty, (<>)) import Data.Profunctor.Product.Newtype -- ProductProfunctor and ProductContravariant are potentially -- redundant type classes. It seems to me that these are equivalent -- to Profunctor with Applicative, and Contravariant with Monoid -- respectively: -- -- import Data.Profunctor -- import Control.Applicative hiding (empty) -- import Data.Functor.Contravariant -- import Data.Monoid -- -- empty :: (Applicative (p ())) => p () () -- empty = pure () -- -- (***!) :: (Applicative (p (a, a')), Profunctor p) => -- p a b -> p a' b' -> p (a, a') (b, b') -- p ***! p' = (,) <$> lmap fst p <*> lmap snd p' -- -- point :: Monoid (f ()) => f () -- point = mempty -- -- (***<) :: (Monoid (f (a, b)), Contravariant f) => -- f a -> f b -> f (a, b) -- p ***< p' = contramap fst p <> contramap snd p' -- -- -- The only thing that makes me think that they are not *completely* -- redundant is that (***!) and (***<) have to be defined -- polymorphically in the type arguments, whereas if we took the -- Profunctor+Applicative or Contravariant+Monoid approach we do not -- have a guarantee that these operations are polymorphic. -- -- Previously I wanted to replace ProductProfunctor and -- ProductContravariant entirely. This proved difficult as it is not -- possible to expand the class constraints to require Applicative and -- Monoid respectively. We can't enforce a constraint 'Applicative (p -- a)' where 'a' does not appear in the head. This seems closely -- related to the above issue of adhoc implementations. -- -- There is a potential method of working around this issue using the -- 'constraints' package: -- stackoverflow.com/questions/12718268/polymorphic-constraint/12718620 -- -- Still, at least we now have default implementations of the class -- methods, which makes things simpler. -- | A 'ProductProfunctor' is a generalization of an 'Applicative'. -- It has an "input", contravariant type parameter on the left as well -- as the usual 'Applicative' "output", covariant parameter on teh -- right. class Profunctor p => ProductProfunctor p where empty :: p () () (***!) :: p a b -> p a' b' -> p (a, a') (b, b') -- This appears to be just 'Data.Functor.Contravariant.Divisible' class Contravariant f => ProductContravariant f where point :: f () (***<) :: f a -> f b -> f (a, b) -- | This is exactly the same as @Applicative@'s @\<*\>@, but for a -- 'ProductProfunctor'. (****) :: ProductProfunctor p => p a (b -> c) -> p a b -> p a c (****) f x = Profunctor.dimap dup (uncurry ($)) (f ***! x) where dup y = (y, y) -- | This is exactly 'Profunctor.rmap', given a name which highlights -- the similarity to @Applicative@'s @\<$\>@. (***$) :: ProductProfunctor p => (b -> c) -> p a b -> p a c (***$) = Profunctor.rmap defaultEmpty :: Applicative (p ()) => p () () defaultEmpty = pure () defaultProfunctorProduct :: (Applicative (p (a, a')), Profunctor p) => p a b -> p a' b' -> p (a, a') (b, b') defaultProfunctorProduct p p' = liftA2 (,) (lmap fst p) (lmap snd p') defaultPoint :: Monoid (p ()) => p () defaultPoint = mempty defaultContravariantProduct :: (Contravariant f, Monoid (f (a, b))) => f a -> f b -> f (a, b) defaultContravariantProduct p p' = contramap fst p <> contramap snd p' newtype PPOfContravariant f a b = PPOfContravariant (f a) unPPOfContravariant :: PPOfContravariant c a a -> c a unPPOfContravariant (PPOfContravariant pp) = pp instance Contravariant f => Profunctor (PPOfContravariant f) where dimap f _ (PPOfContravariant p) = PPOfContravariant (contramap f p) instance ProductContravariant f => ProductProfunctor (PPOfContravariant f) where empty = PPOfContravariant point PPOfContravariant f ***! PPOfContravariant f' = PPOfContravariant (f ***< f') instance ProductProfunctor (->) where empty = id (***!) = (***) instance Arrow arr => ProductProfunctor (WrappedArrow arr) where empty = id (***!) = (***) data AndArrow arr z a b = AndArrow { runAndArrow :: arr z b } instance Arrow arr => Profunctor (AndArrow arr z) where dimap _ f (AndArrow g) = AndArrow (arr f <<< g) instance Arrow arr => ProductProfunctor (AndArrow arr z) where empty = AndArrow (arr (const ())) (AndArrow f) ***! (AndArrow f') = AndArrow (f &&& f') -- { Sum class Profunctor p => SumProfunctor p where -- Morally we should have 'zero :: p Void Void' but I don't think -- that would actually be useful (+++!) :: p a b -> p a' b' -> p (Either a a') (Either b b') instance SumProfunctor (->) where f +++! g = either (Left . f) (Right . g) list :: (ProductProfunctor p, SumProfunctor p) => p a b -> p [a] [b] list p = Profunctor.dimap fromList toList (empty +++! (p ***! list p)) where toList :: Either () (a, [a]) -> [a] toList = either (const []) (uncurry (:)) fromList :: [a] -> Either () (a, [a]) fromList [] = Left () fromList (a:as) = Right (a, as) -- SumContravariant would be 'Data.Functor.Contravariant.Decidable' -- (without the requirement to also be Divisible). -- } pT0 :: ProductProfunctor p => T0 -> p T0 T0 pT0 = const empty pT1 :: ProductProfunctor p => T1 (p a1 b1) -> p (T1 a1) (T1 b1) pT1 = id pT2 :: ProductProfunctor p => T2 (p a1 b1) (p a2 b2) -> p (T2 a1 a2) (T2 b1 b2) pT2 = uncurry (***!) chain :: ProductProfunctor p => (t -> p a2 b2) -> (p a1 b1, t) -> p (a1, a2) (b1, b2) chain rest (a, as) = pT2 (a, rest as) pT3 :: ProductProfunctor p => T3 (p a1 b1) (p a2 b2) (p a3 b3) -> p (T3 a1 a2 a3) (T3 b1 b2 b3) pT3 = chain pT2 pT4 :: ProductProfunctor p => T4 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) -> p (T4 a1 a2 a3 a4) (T4 b1 b2 b3 b4) pT4 = chain pT3 pT5 :: ProductProfunctor p => T5 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) -> p (T5 a1 a2 a3 a4 a5) (T5 b1 b2 b3 b4 b5) pT5 = chain pT4 pT6 :: ProductProfunctor p => T6 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) -> p (T6 a1 a2 a3 a4 a5 a6) (T6 b1 b2 b3 b4 b5 b6) pT6 = chain pT5 pT7 :: ProductProfunctor p => T7 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) -> p (T7 a1 a2 a3 a4 a5 a6 a7) (T7 b1 b2 b3 b4 b5 b6 b7) pT7 = chain pT6 pT8 :: ProductProfunctor p => T8 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) -> p (T8 a1 a2 a3 a4 a5 a6 a7 a8) (T8 b1 b2 b3 b4 b5 b6 b7 b8) pT8 = chain pT7 pT9 :: ProductProfunctor p => T9 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) -> p (T9 a1 a2 a3 a4 a5 a6 a7 a8 a9) (T9 b1 b2 b3 b4 b5 b6 b7 b8 b9) pT9 = chain pT8 pT10 :: ProductProfunctor p => T10 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) -> p (T10 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10) (T10 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10) pT10 = chain pT9 pT11 :: ProductProfunctor p => T11 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) -> p (T11 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11) (T11 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11) pT11 = chain pT10 pT12 :: ProductProfunctor p => T12 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) -> p (T12 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12) (T12 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12) pT12 = chain pT11 pT13 :: ProductProfunctor p => T13 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) -> p (T13 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13) (T13 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13) pT13 = chain pT12 pT14 :: ProductProfunctor p => T14 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) -> p (T14 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14) (T14 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14) pT14 = chain pT13 pT15 :: ProductProfunctor p => T15 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) -> p (T15 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15) (T15 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15) pT15 = chain pT14 pT16 :: ProductProfunctor p => T16 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) (p a16 b16) -> p (T16 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16) (T16 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16) pT16 = chain pT15 pT17 :: ProductProfunctor p => T17 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) (p a16 b16) (p a17 b17) -> p (T17 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17) (T17 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17) pT17 = chain pT16 pT18 :: ProductProfunctor p => T18 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) (p a16 b16) (p a17 b17) (p a18 b18) -> p (T18 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18) (T18 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18) pT18 = chain pT17 pT19 :: ProductProfunctor p => T19 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) (p a16 b16) (p a17 b17) (p a18 b18) (p a19 b19) -> p (T19 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19) (T19 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19) pT19 = chain pT18 pT20 :: ProductProfunctor p => T20 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) (p a16 b16) (p a17 b17) (p a18 b18) (p a19 b19) (p a20 b20) -> p (T20 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20) (T20 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20) pT20 = chain pT19 pT21 :: ProductProfunctor p => T21 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) (p a16 b16) (p a17 b17) (p a18 b18) (p a19 b19) (p a20 b20) (p a21 b21) -> p (T21 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21) (T21 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20 b21) pT21 = chain pT20 pT22 :: ProductProfunctor p => T22 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) (p a16 b16) (p a17 b17) (p a18 b18) (p a19 b19) (p a20 b20) (p a21 b21) (p a22 b22) -> p (T22 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22) (T22 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20 b21 b22) pT22 = chain pT21 pT23 :: ProductProfunctor p => T23 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) (p a16 b16) (p a17 b17) (p a18 b18) (p a19 b19) (p a20 b20) (p a21 b21) (p a22 b22) (p a23 b23) -> p (T23 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22 a23) (T23 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20 b21 b22 b23) pT23 = chain pT22 pT24 :: ProductProfunctor p => T24 (p a1 b1) (p a2 b2) (p a3 b3) (p a4 b4) (p a5 b5) (p a6 b6) (p a7 b7) (p a8 b8) (p a9 b9) (p a10 b10) (p a11 b11) (p a12 b12) (p a13 b13) (p a14 b14) (p a15 b15) (p a16 b16) (p a17 b17) (p a18 b18) (p a19 b19) (p a20 b20) (p a21 b21) (p a22 b22) (p a23 b23) (p a24 b24) -> p (T24 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22 a23 a24) (T24 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20 b21 b22 b23 b24) pT24 = chain pT23 convert :: Profunctor p => (a2 -> a1) -> (tp -> tTp) -> (b1 -> b2) -> (tTp -> p a1 b1) -> tp -> p a2 b2 convert u u' f c = dimap u f . c . u' p0 :: ProductProfunctor p => () -> p () () p0 = convert unflatten0 unflatten0 flatten0 pT0 p1 :: ProductProfunctor p => p a1 b1 -> p a1 b1 p1 = convert unflatten1 unflatten1 flatten1 pT1 p2 :: ProductProfunctor p => (p a1 b1, p a2 b2) -> p (a1, a2) (b1, b2) p2 = convert unflatten2 unflatten2 flatten2 pT2 p3 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3) -> p (a1, a2, a3) (b1, b2, b3) p3 = convert unflatten3 unflatten3 flatten3 pT3 p4 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4) -> p (a1, a2, a3, a4) (b1, b2, b3, b4) p4 = convert unflatten4 unflatten4 flatten4 pT4 p5 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5) -> p (a1, a2, a3, a4, a5) (b1, b2, b3, b4, b5) p5 = convert unflatten5 unflatten5 flatten5 pT5 p6 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6) -> p (a1, a2, a3, a4, a5, a6) (b1, b2, b3, b4, b5, b6) p6 = convert unflatten6 unflatten6 flatten6 pT6 p7 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7) -> p (a1, a2, a3, a4, a5, a6, a7) (b1, b2, b3, b4, b5, b6, b7) p7 = convert unflatten7 unflatten7 flatten7 pT7 p8 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8) -> p (a1, a2, a3, a4, a5, a6, a7, a8) (b1, b2, b3, b4, b5, b6, b7, b8) p8 = convert unflatten8 unflatten8 flatten8 pT8 p9 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9) (b1, b2, b3, b4, b5, b6, b7, b8, b9) p9 = convert unflatten9 unflatten9 flatten9 pT9 p10 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10) p10 = convert unflatten10 unflatten10 flatten10 pT10 p11 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11) p11 = convert unflatten11 unflatten11 flatten11 pT11 p12 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12) p12 = convert unflatten12 unflatten12 flatten12 pT12 p13 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13) p13 = convert unflatten13 unflatten13 flatten13 pT13 p14 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14) p14 = convert unflatten14 unflatten14 flatten14 pT14 p15 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15) p15 = convert unflatten15 unflatten15 flatten15 pT15 p16 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15, p a16 b16) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16) p16 = convert unflatten16 unflatten16 flatten16 pT16 p17 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15, p a16 b16, p a17 b17) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17) p17 = convert unflatten17 unflatten17 flatten17 pT17 p18 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15, p a16 b16, p a17 b17, p a18 b18) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18) p18 = convert unflatten18 unflatten18 flatten18 pT18 p19 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15, p a16 b16, p a17 b17, p a18 b18, p a19 b19) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19) p19 = convert unflatten19 unflatten19 flatten19 pT19 p20 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15, p a16 b16, p a17 b17, p a18 b18, p a19 b19, p a20 b20) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20) p20 = convert unflatten20 unflatten20 flatten20 pT20 p21 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15, p a16 b16, p a17 b17, p a18 b18, p a19 b19, p a20 b20, p a21 b21) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21) p21 = convert unflatten21 unflatten21 flatten21 pT21 p22 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15, p a16 b16, p a17 b17, p a18 b18, p a19 b19, p a20 b20, p a21 b21, p a22 b22) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22) p22 = convert unflatten22 unflatten22 flatten22 pT22 p23 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15, p a16 b16, p a17 b17, p a18 b18, p a19 b19, p a20 b20, p a21 b21, p a22 b22, p a23 b23) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23) p23 = convert unflatten23 unflatten23 flatten23 pT23 p24 :: ProductProfunctor p => (p a1 b1, p a2 b2, p a3 b3, p a4 b4, p a5 b5, p a6 b6, p a7 b7, p a8 b8, p a9 b9, p a10 b10, p a11 b11, p a12 b12, p a13 b13, p a14 b14, p a15 b15, p a16 b16, p a17 b17, p a18 b18, p a19 b19, p a20 b20, p a21 b21, p a22 b22, p a23 b23, p a24 b24) -> p (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24) (b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24) p24 = convert unflatten24 unflatten24 flatten24 pT24