    {-# LANGUAGE PolyKinds #-}
    module Barbies.Generics.Traversable
      ( GTraversable(..)
      )

    where

    import Data.Generics.GenericN
    import Data.Proxy (Proxy (..))

    class GTraversable n f g repbf repbg where
      gtraverse
        :: Applicative t
        => Proxy n
        -> (forall a . f a -> t (g a))
        -> repbf x
        -> t (repbg x)

    -- ----------------------------------
    -- Trivial cases
    -- ----------------------------------

    instance
      ( GTraversable n f g bf bg
      ) => GTraversable n f g (M1 i c bf) (M1 i c bg)
      where
      gtraverse :: forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a))
    -> M1 i c bf x
    -> t (M1 i c bg x)
    gtraverse Proxy n
    pn forall (a :: k). f a -> t (g a)
    h
        = (bg x -> M1 i c bg x) -> t (bg x) -> t (M1 i c bg x)
    forall a b. (a -> b) -> t a -> t b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap bg x -> M1 i c bg x
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1 (t (bg x) -> t (M1 i c bg x))
    -> (M1 i c bf x -> t (bg x)) -> M1 i c bf x -> t (M1 i c bg x)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Proxy n -> (forall (a :: k). f a -> t (g a)) -> bf x -> t (bg x)
    forall {k} {k} {k} (n :: k) (f :: k -> *) (g :: k -> *)
           (repbf :: k -> *) (repbg :: k -> *) (t :: * -> *) (x :: k).
    (GTraversable n f g repbf repbg, Applicative t) =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a)) -> repbf x -> t (repbg x)
    forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n -> (forall (a :: k). f a -> t (g a)) -> bf x -> t (bg x)
    gtraverse Proxy n
    pn f a -> t (g a)
    forall (a :: k). f a -> t (g a)
    h (bf x -> t (bg x))
    -> (M1 i c bf x -> bf x) -> M1 i c bf x -> t (bg x)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . M1 i c bf x -> bf x
    forall k i (c :: Meta) (f :: k -> *) (p :: k). M1 i c f p -> f p
    unM1
      {-# INLINE gtraverse #-}

    instance GTraversable n f g V1 V1 where
      gtraverse :: forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n -> (forall (a :: k). f a -> t (g a)) -> V1 x -> t (V1 x)
    gtraverse Proxy n
    _ forall (a :: k). f a -> t (g a)
    _ V1 x
    _ = t (V1 x)
    forall a. HasCallStack => a
    undefined
      {-# INLINE gtraverse #-}

    instance GTraversable n f g U1 U1 where
      gtraverse :: forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n -> (forall (a :: k). f a -> t (g a)) -> U1 x -> t (U1 x)
    gtraverse Proxy n
    _ forall (a :: k). f a -> t (g a)
    _ = U1 x -> t (U1 x)
    forall a. a -> t a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      {-# INLINE gtraverse #-}

    instance
      ( GTraversable n f g l l'
      , GTraversable n f g r r'
      ) => GTraversable n f g (l :*: r) (l' :*: r')
      where
      gtraverse :: forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a))
    -> (:*:) l r x
    -> t ((:*:) l' r' x)
    gtraverse Proxy n
    pn forall (a :: k). f a -> t (g a)
    h (l x
    l :*: r x
    r)
        = l' x -> r' x -> (:*:) l' r' x
    forall k (f :: k -> *) (g :: k -> *) (p :: k).
    f p -> g p -> (:*:) f g p
    (:*:) (l' x -> r' x -> (:*:) l' r' x)
    -> t (l' x) -> t (r' x -> (:*:) l' r' x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy n -> (forall (a :: k). f a -> t (g a)) -> l x -> t (l' x)
    forall {k} {k} {k} (n :: k) (f :: k -> *) (g :: k -> *)
           (repbf :: k -> *) (repbg :: k -> *) (t :: * -> *) (x :: k).
    (GTraversable n f g repbf repbg, Applicative t) =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a)) -> repbf x -> t (repbg x)
    forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n -> (forall (a :: k). f a -> t (g a)) -> l x -> t (l' x)
    gtraverse Proxy n
    pn f a -> t (g a)
    forall (a :: k). f a -> t (g a)
    h l x
    l t (r' x -> (:*:) l' r' x) -> t (r' x) -> t ((:*:) l' r' x)
    forall a b. t (a -> b) -> t a -> t b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Proxy n -> (forall (a :: k). f a -> t (g a)) -> r x -> t (r' x)
    forall {k} {k} {k} (n :: k) (f :: k -> *) (g :: k -> *)
           (repbf :: k -> *) (repbg :: k -> *) (t :: * -> *) (x :: k).
    (GTraversable n f g repbf repbg, Applicative t) =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a)) -> repbf x -> t (repbg x)
    forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n -> (forall (a :: k). f a -> t (g a)) -> r x -> t (r' x)
    gtraverse Proxy n
    pn f a -> t (g a)
    forall (a :: k). f a -> t (g a)
    h r x
    r
      {-# INLINE gtraverse #-}

    instance
      ( GTraversable n f g l l'
      , GTraversable n f g r r'
      ) => GTraversable n f g (l :+: r) (l' :+: r')
      where
      gtraverse :: forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a))
    -> (:+:) l r x
    -> t ((:+:) l' r' x)
    gtraverse Proxy n
    pn forall (a :: k). f a -> t (g a)
    h = \case
        L1 l x
    l -> l' x -> (:+:) l' r' x
    forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
    L1 (l' x -> (:+:) l' r' x) -> t (l' x) -> t ((:+:) l' r' x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy n -> (forall (a :: k). f a -> t (g a)) -> l x -> t (l' x)
    forall {k} {k} {k} (n :: k) (f :: k -> *) (g :: k -> *)
           (repbf :: k -> *) (repbg :: k -> *) (t :: * -> *) (x :: k).
    (GTraversable n f g repbf repbg, Applicative t) =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a)) -> repbf x -> t (repbg x)
    forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n -> (forall (a :: k). f a -> t (g a)) -> l x -> t (l' x)
    gtraverse Proxy n
    pn f a -> t (g a)
    forall (a :: k). f a -> t (g a)
    h l x
    l
        R1 r x
    r -> r' x -> (:+:) l' r' x
    forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
    R1 (r' x -> (:+:) l' r' x) -> t (r' x) -> t ((:+:) l' r' x)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy n -> (forall (a :: k). f a -> t (g a)) -> r x -> t (r' x)
    forall {k} {k} {k} (n :: k) (f :: k -> *) (g :: k -> *)
           (repbf :: k -> *) (repbg :: k -> *) (t :: * -> *) (x :: k).
    (GTraversable n f g repbf repbg, Applicative t) =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a)) -> repbf x -> t (repbg x)
    forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n -> (forall (a :: k). f a -> t (g a)) -> r x -> t (r' x)
    gtraverse Proxy n
    pn f a -> t (g a)
    forall (a :: k). f a -> t (g a)
    h r x
    r
      {-# INLINE gtraverse #-}

    -- --------------------------------
    -- The interesting cases
    -- --------------------------------

    type P = Param

    -- {{ Functor application ------------------------------------------------------
    instance
      GTraversable n f g (Rec (P n f a') (f a))
                         (Rec (P n g a') (g a))
      where
      gtraverse :: forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a))
    -> Rec (P n f a') (f a) x
    -> t (Rec (P n g a') (g a) x)
    gtraverse Proxy n
    _ forall (a :: k). f a -> t (g a)
    h
        = (g a -> Rec (P n g a') (g a) x)
    -> t (g a) -> t (Rec (P n g a') (g a) x)
    forall a b. (a -> b) -> t a -> t b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (K1 R (g a) x -> Rec (P n g a') (g a) x
    forall {k} p a (x :: k). K1 R a x -> Rec p a x
    Rec (K1 R (g a) x -> Rec (P n g a') (g a) x)
    -> (g a -> K1 R (g a) x) -> g a -> Rec (P n g a') (g a) x
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . g a -> K1 R (g a) x
    forall k i c (p :: k). c -> K1 i c p
    K1) (t (g a) -> t (Rec (P n g a') (g a) x))
    -> (Rec (P n f a') (f a) x -> t (g a))
    -> Rec (P n f a') (f a) x
    -> t (Rec (P n g a') (g a) x)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . f a -> t (g a)
    forall (a :: k). f a -> t (g a)
    h (f a -> t (g a))
    -> (Rec (P n f a') (f a) x -> f a)
    -> Rec (P n f a') (f a) x
    -> t (g a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . K1 R (f a) x -> f a
    forall k i c (p :: k). K1 i c p -> c
    unK1 (K1 R (f a) x -> f a)
    -> (Rec (P n f a') (f a) x -> K1 R (f a) x)
    -> Rec (P n f a') (f a) x
    -> f a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Rec (P n f a') (f a) x -> K1 R (f a) x
    forall {k} p a (x :: k). Rec p a x -> K1 R a x
    unRec
      {-# INLINE gtraverse #-}

    instance
      ( Traversable h
      ) =>
      GTraversable n f g (Rec (h (P n f a)) (h (f a)))
                         (Rec (h (P n g a)) (h (g a)))
      where
      gtraverse :: forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a))
    -> Rec (h (P n f a)) (h (f a)) x
    -> t (Rec (h (P n g a)) (h (g a)) x)
    gtraverse Proxy n
    _ forall (a :: k). f a -> t (g a)
    h
        = (h (g a) -> Rec (h (P n g a)) (h (g a)) x)
    -> t (h (g a)) -> t (Rec (h (P n g a)) (h (g a)) x)
    forall a b. (a -> b) -> t a -> t b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (K1 R (h (g a)) x -> Rec (h (P n g a)) (h (g a)) x
    forall {k} p a (x :: k). K1 R a x -> Rec p a x
    Rec (K1 R (h (g a)) x -> Rec (h (P n g a)) (h (g a)) x)
    -> (h (g a) -> K1 R (h (g a)) x)
    -> h (g a)
    -> Rec (h (P n g a)) (h (g a)) x
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . h (g a) -> K1 R (h (g a)) x
    forall k i c (p :: k). c -> K1 i c p
    K1) (t (h (g a)) -> t (Rec (h (P n g a)) (h (g a)) x))
    -> (Rec (h (P n f a)) (h (f a)) x -> t (h (g a)))
    -> Rec (h (P n f a)) (h (f a)) x
    -> t (Rec (h (P n g a)) (h (g a)) x)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (f a -> t (g a)) -> h (f a) -> t (h (g a))
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> h a -> f (h b)
    traverse f a -> t (g a)
    forall (a :: k). f a -> t (g a)
    h (h (f a) -> t (h (g a)))
    -> (Rec (h (P n f a)) (h (f a)) x -> h (f a))
    -> Rec (h (P n f a)) (h (f a)) x
    -> t (h (g a))
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . K1 R (h (f a)) x -> h (f a)
    forall k i c (p :: k). K1 i c p -> c
    unK1 (K1 R (h (f a)) x -> h (f a))
    -> (Rec (h (P n f a)) (h (f a)) x -> K1 R (h (f a)) x)
    -> Rec (h (P n f a)) (h (f a)) x
    -> h (f a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Rec (h (P n f a)) (h (f a)) x -> K1 R (h (f a)) x
    forall {k} p a (x :: k). Rec p a x -> K1 R a x
    unRec
      {-# INLINE gtraverse #-}
    -- }} Functor application ------------------------------------------------------

    -- {{ Not a functor application -----------------------------------------------
    instance GTraversable n f g (Rec a a) (Rec a a) where
      gtraverse :: forall (t :: * -> *) (x :: k).
    Applicative t =>
    Proxy n
    -> (forall (a :: k). f a -> t (g a)) -> Rec a a x -> t (Rec a a x)
    gtraverse Proxy n
    _ forall (a :: k). f a -> t (g a)
    _ = Rec a a x -> t (Rec a a x)
    forall a. a -> t a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      {-# INLINE gtraverse #-}
    -- }} Not a functor application -----------------------------------------------