    -- |
    -- Module      : Foundation.Collection.Zippable
    -- License     : BSD-style
    -- Maintainer  : foundation
    -- Stability   : experimental
    -- Portability : portable
    --
    -- Common functions (e. g. 'zip', 'zipWith') that are useful for combining
    -- multiple collections.
    --
    {-# LANGUAGE FlexibleInstances     #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE StandaloneDeriving    #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    module Foundation.Collection.Zippable
        ( BoxedZippable(..)
        , Zippable(..)
        ) where

    import qualified Basement.UArray as UV
    import qualified Basement.BoxedArray as BA
    import qualified Basement.String as S
    import           Foundation.Collection.Element
    import           Foundation.Collection.Sequential
    import           Basement.Compat.Base
    import           Basement.Types.AsciiString(AsciiString(..))
    import qualified Prelude
    import           GHC.ST

    class Sequential col => Zippable col where

      -- | 'zipWith' generalises 'zip' by zipping with the function given as the
      --   first argument, instead of a tupling function. For example, @'zipWith' (+)@
      --   is applied to two collections to produce the collection of corresponding
      --   sums.
      zipWith :: (Sequential a, Sequential b)
              => (Element a -> Element b -> Element col)
              -> a -> b -> col
      zipWith f :: Element a -> Element b -> Element col
    f a :: a
    a b :: b
    b = (Element [Element a] -> Element [Element b] -> Element col)
    -> ([Element a], [Element b]) -> col
    forall c a b.
    (Sequential c, Sequential a, Sequential b) =>
    (Element a -> Element b -> Element c) -> (a, b) -> c
    go Element a -> Element b -> Element col
    Element [Element a] -> Element [Element b] -> Element col
    f (a -> [Item a]
    forall l. IsList l => l -> [Item l]
    toList a
    a, b -> [Item b]
    forall l. IsList l => l -> [Item l]
    toList b
    b)
        where go :: (Element a -> Element b -> Element c) -> (a, b) -> c
    go f' :: Element a -> Element b -> Element c
    f' = c
    -> (((Element a, Element b), (a, b)) -> c)
    -> Maybe ((Element a, Element b), (a, b))
    -> c
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe c
    forall a. Monoid a => a
    mempty (\(x :: (Element a, Element b)
    x, xs :: (a, b)
    xs) -> (Element a -> Element b -> Element c)
    -> (Element a, Element b) -> Element c
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry2 Element a -> Element b -> Element c
    f' (Element a, Element b)
    x Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` (Element a -> Element b -> Element c) -> (a, b) -> c
    go Element a -> Element b -> Element c
    f' (a, b)
    xs) (Maybe ((Element a, Element b), (a, b)) -> c)
    -> ((a, b) -> Maybe ((Element a, Element b), (a, b)))
    -> (a, b)
    -> c
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . (a, b) -> Maybe ((Element a, Element b), (a, b))
    forall a b.
    (Sequential a, Sequential b) =>
    (a, b) -> Maybe ((Element a, Element b), (a, b))
    uncons2

      -- | Like 'zipWith', but works with 3 collections.
      zipWith3 :: (Sequential a, Sequential b, Sequential c)
               => (Element a -> Element b -> Element c -> Element col)
               -> a -> b -> c -> col
      zipWith3 f :: Element a -> Element b -> Element c -> Element col
    f a :: a
    a b :: b
    b c :: c
    c = (Element [Element a]
     -> Element [Element b] -> Element [Element c] -> Element col)
    -> ([Element a], [Element b], [Element c]) -> col
    forall c a b c.
    (Sequential c, Sequential a, Sequential b, Sequential c) =>
    (Element a -> Element b -> Element c -> Element c)
    -> (a, b, c) -> c
    go Element a -> Element b -> Element c -> Element col
    Element [Element a]
    -> Element [Element b] -> Element [Element c] -> Element col
    f (a -> [Item a]
    forall l. IsList l => l -> [Item l]
    toList a
    a, b -> [Item b]
    forall l. IsList l => l -> [Item l]
    toList b
    b, c -> [Item c]
    forall l. IsList l => l -> [Item l]
    toList c
    c)
        where go :: (Element a -> Element b -> Element c -> Element c)
    -> (a, b, c) -> c
    go f' :: Element a -> Element b -> Element c -> Element c
    f' = c
    -> (((Element a, Element b, Element c), (a, b, c)) -> c)
    -> Maybe ((Element a, Element b, Element c), (a, b, c))
    -> c
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe c
    forall a. Monoid a => a
    mempty (\(x :: (Element a, Element b, Element c)
    x, xs :: (a, b, c)
    xs) -> (Element a -> Element b -> Element c -> Element c)
    -> (Element a, Element b, Element c) -> Element c
    forall a b c d. (a -> b -> c -> d) -> (a, b, c) -> d
    uncurry3 Element a -> Element b -> Element c -> Element c
    f' (Element a, Element b, Element c)
    x Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` (Element a -> Element b -> Element c -> Element c)
    -> (a, b, c) -> c
    go Element a -> Element b -> Element c -> Element c
    f' (a, b, c)
    xs) (Maybe ((Element a, Element b, Element c), (a, b, c)) -> c)
    -> ((a, b, c)
        -> Maybe ((Element a, Element b, Element c), (a, b, c)))
    -> (a, b, c)
    -> c
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . (a, b, c) -> Maybe ((Element a, Element b, Element c), (a, b, c))
    forall a b c.
    (Sequential a, Sequential b, Sequential c) =>
    (a, b, c) -> Maybe ((Element a, Element b, Element c), (a, b, c))
    uncons3

      -- | Like 'zipWith', but works with 4 collections.
      zipWith4 :: (Sequential a, Sequential b, Sequential c, Sequential d)
               => (Element a -> Element b -> Element c -> Element d -> Element col)
               -> a -> b -> c -> d -> col
      zipWith4 fn :: Element a -> Element b -> Element c -> Element d -> Element col
    fn a :: a
    a b :: b
    b c :: c
    c d :: d
    d = (Element [Element a]
     -> Element [Element b]
     -> Element [Element c]
     -> Element [Element d]
     -> Element col)
    -> ([Element a], [Element b], [Element c], [Element d]) -> col
    forall c a b c d.
    (Sequential c, Sequential a, Sequential b, Sequential c,
     Sequential d) =>
    (Element a -> Element b -> Element c -> Element d -> Element c)
    -> (a, b, c, d) -> c
    go Element a -> Element b -> Element c -> Element d -> Element col
    Element [Element a]
    -> Element [Element b]
    -> Element [Element c]
    -> Element [Element d]
    -> Element col
    fn (a -> [Item a]
    forall l. IsList l => l -> [Item l]
    toList a
    a, b -> [Item b]
    forall l. IsList l => l -> [Item l]
    toList b
    b, c -> [Item c]
    forall l. IsList l => l -> [Item l]
    toList c
    c, d -> [Item d]
    forall l. IsList l => l -> [Item l]
    toList d
    d)
        where go :: (Element a -> Element b -> Element c -> Element d -> Element c)
    -> (a, b, c, d) -> c
    go f' :: Element a -> Element b -> Element c -> Element d -> Element c
    f' = c
    -> (((Element a, Element b, Element c, Element d), (a, b, c, d))
        -> c)
    -> Maybe
         ((Element a, Element b, Element c, Element d), (a, b, c, d))
    -> c
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe c
    forall a. Monoid a => a
    mempty (\(x :: (Element a, Element b, Element c, Element d)
    x, xs :: (a, b, c, d)
    xs) -> (Element a -> Element b -> Element c -> Element d -> Element c)
    -> (Element a, Element b, Element c, Element d) -> Element c
    forall a b c d g. (a -> b -> c -> d -> g) -> (a, b, c, d) -> g
    uncurry4 Element a -> Element b -> Element c -> Element d -> Element c
    f' (Element a, Element b, Element c, Element d)
    x Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` (Element a -> Element b -> Element c -> Element d -> Element c)
    -> (a, b, c, d) -> c
    go Element a -> Element b -> Element c -> Element d -> Element c
    f' (a, b, c, d)
    xs) (Maybe ((Element a, Element b, Element c, Element d), (a, b, c, d))
     -> c)
    -> ((a, b, c, d)
        -> Maybe
             ((Element a, Element b, Element c, Element d), (a, b, c, d)))
    -> (a, b, c, d)
    -> c
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . (a, b, c, d)
    -> Maybe
         ((Element a, Element b, Element c, Element d), (a, b, c, d))
    forall a b c d.
    (Sequential a, Sequential b, Sequential c, Sequential d) =>
    (a, b, c, d)
    -> Maybe
         ((Element a, Element b, Element c, Element d), (a, b, c, d))
    uncons4

      -- | Like 'zipWith', but works with 5 collections.
      zipWith5 :: (Sequential a, Sequential b, Sequential c, Sequential d, Sequential e)
               => (Element a -> Element b -> Element c -> Element d -> Element e -> Element col)
               -> a -> b -> c -> d -> e -> col
      zipWith5 fn :: Element a
    -> Element b -> Element c -> Element d -> Element e -> Element col
    fn a :: a
    a b :: b
    b c :: c
    c d :: d
    d e :: e
    e = (Element [Element a]
     -> Element [Element b]
     -> Element [Element c]
     -> Element [Element d]
     -> Element [Element e]
     -> Element col)
    -> ([Element a], [Element b], [Element c], [Element d],
        [Element e])
    -> col
    forall c a b c d e.
    (Sequential c, Sequential a, Sequential b, Sequential c,
     Sequential d, Sequential e) =>
    (Element a
     -> Element b -> Element c -> Element d -> Element e -> Element c)
    -> (a, b, c, d, e) -> c
    go Element a
    -> Element b -> Element c -> Element d -> Element e -> Element col
    Element [Element a]
    -> Element [Element b]
    -> Element [Element c]
    -> Element [Element d]
    -> Element [Element e]
    -> Element col
    fn (a -> [Item a]
    forall l. IsList l => l -> [Item l]
    toList a
    a, b -> [Item b]
    forall l. IsList l => l -> [Item l]
    toList b
    b, c -> [Item c]
    forall l. IsList l => l -> [Item l]
    toList c
    c, d -> [Item d]
    forall l. IsList l => l -> [Item l]
    toList d
    d, e -> [Item e]
    forall l. IsList l => l -> [Item l]
    toList e
    e)
        where go :: (Element a
     -> Element b -> Element c -> Element d -> Element e -> Element c)
    -> (a, b, c, d, e) -> c
    go f' :: Element a
    -> Element b -> Element c -> Element d -> Element e -> Element c
    f' = c
    -> (((Element a, Element b, Element c, Element d, Element e),
         (a, b, c, d, e))
        -> c)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e),
          (a, b, c, d, e))
    -> c
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe c
    forall a. Monoid a => a
    mempty (\(x :: (Element a, Element b, Element c, Element d, Element e)
    x, xs :: (a, b, c, d, e)
    xs) -> (Element a
     -> Element b -> Element c -> Element d -> Element e -> Element c)
    -> (Element a, Element b, Element c, Element d, Element e)
    -> Element c
    forall a b c d e f.
    (a -> b -> c -> d -> e -> f) -> (a, b, c, d, e) -> f
    uncurry5 Element a
    -> Element b -> Element c -> Element d -> Element e -> Element c
    f' (Element a, Element b, Element c, Element d, Element e)
    x Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` (Element a
     -> Element b -> Element c -> Element d -> Element e -> Element c)
    -> (a, b, c, d, e) -> c
    go Element a
    -> Element b -> Element c -> Element d -> Element e -> Element c
    f' (a, b, c, d, e)
    xs) (Maybe
       ((Element a, Element b, Element c, Element d, Element e),
        (a, b, c, d, e))
     -> c)
    -> ((a, b, c, d, e)
        -> Maybe
             ((Element a, Element b, Element c, Element d, Element e),
              (a, b, c, d, e)))
    -> (a, b, c, d, e)
    -> c
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . (a, b, c, d, e)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e),
          (a, b, c, d, e))
    forall a b c d e.
    (Sequential a, Sequential b, Sequential c, Sequential d,
     Sequential e) =>
    (a, b, c, d, e)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e),
          (a, b, c, d, e))
    uncons5

      -- | Like 'zipWith', but works with 6 collections.
      zipWith6 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e
                  , Sequential f)
               => (Element a -> Element b -> Element c -> Element d -> Element e -> Element f -> Element col)
               -> a -> b -> c -> d -> e -> f -> col
      zipWith6 fn :: Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element col
    fn a :: a
    a b :: b
    b c :: c
    c d :: d
    d e :: e
    e f :: f
    f = (Element [Element a]
     -> Element [Element b]
     -> Element [Element c]
     -> Element [Element d]
     -> Element [Element e]
     -> Element [Element f]
     -> Element col)
    -> ([Element a], [Element b], [Element c], [Element d],
        [Element e], [Element f])
    -> col
    forall c a b c d e f.
    (Sequential c, Sequential a, Sequential b, Sequential c,
     Sequential d, Sequential e, Sequential f) =>
    (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element c)
    -> (a, b, c, d, e, f) -> c
    go Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element col
    Element [Element a]
    -> Element [Element b]
    -> Element [Element c]
    -> Element [Element d]
    -> Element [Element e]
    -> Element [Element f]
    -> Element col
    fn (a -> [Item a]
    forall l. IsList l => l -> [Item l]
    toList a
    a, b -> [Item b]
    forall l. IsList l => l -> [Item l]
    toList b
    b, c -> [Item c]
    forall l. IsList l => l -> [Item l]
    toList c
    c, d -> [Item d]
    forall l. IsList l => l -> [Item l]
    toList d
    d, e -> [Item e]
    forall l. IsList l => l -> [Item l]
    toList e
    e, f -> [Item f]
    forall l. IsList l => l -> [Item l]
    toList f
    f)
        where go :: (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element c)
    -> (a, b, c, d, e, f) -> c
    go f' :: Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element c
    f' = c
    -> (((Element a, Element b, Element c, Element d, Element e,
          Element f),
         (a, b, c, d, e, f))
        -> c)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e,
           Element f),
          (a, b, c, d, e, f))
    -> c
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe c
    forall a. Monoid a => a
    mempty (\(x :: (Element a, Element b, Element c, Element d, Element e, Element f)
    x, xs :: (a, b, c, d, e, f)
    xs) -> (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element c)
    -> (Element a, Element b, Element c, Element d, Element e,
        Element f)
    -> Element c
    forall a b c d e f g.
    (a -> b -> c -> d -> e -> f -> g) -> (a, b, c, d, e, f) -> g
    uncurry6 Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element c
    f' (Element a, Element b, Element c, Element d, Element e, Element f)
    x Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element c)
    -> (a, b, c, d, e, f) -> c
    go Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element c
    f' (a, b, c, d, e, f)
    xs) (Maybe
       ((Element a, Element b, Element c, Element d, Element e,
         Element f),
        (a, b, c, d, e, f))
     -> c)
    -> ((a, b, c, d, e, f)
        -> Maybe
             ((Element a, Element b, Element c, Element d, Element e,
               Element f),
              (a, b, c, d, e, f)))
    -> (a, b, c, d, e, f)
    -> c
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . (a, b, c, d, e, f)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e,
           Element f),
          (a, b, c, d, e, f))
    forall a b c d e f.
    (Sequential a, Sequential b, Sequential c, Sequential d,
     Sequential e, Sequential f) =>
    (a, b, c, d, e, f)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e,
           Element f),
          (a, b, c, d, e, f))
    uncons6

      -- | Like 'zipWith', but works with 7 collections.
      zipWith7 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e
                  , Sequential f, Sequential g )
               => (Element a -> Element b -> Element c -> Element d -> Element e -> Element f -> Element g -> Element col)
               -> a -> b -> c -> d -> e -> f -> g -> col
      zipWith7 fn :: Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element g
    -> Element col
    fn a :: a
    a b :: b
    b c :: c
    c d :: d
    d e :: e
    e f :: f
    f g :: g
    g = (Element [Element a]
     -> Element [Element b]
     -> Element [Element c]
     -> Element [Element d]
     -> Element [Element e]
     -> Element [Element f]
     -> Element [Element g]
     -> Element col)
    -> ([Element a], [Element b], [Element c], [Element d],
        [Element e], [Element f], [Element g])
    -> col
    forall c a b c d e f g.
    (Sequential c, Sequential a, Sequential b, Sequential c,
     Sequential d, Sequential e, Sequential f, Sequential g) =>
    (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element g
     -> Element c)
    -> (a, b, c, d, e, f, g) -> c
    go Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element g
    -> Element col
    Element [Element a]
    -> Element [Element b]
    -> Element [Element c]
    -> Element [Element d]
    -> Element [Element e]
    -> Element [Element f]
    -> Element [Element g]
    -> Element col
    fn (a -> [Item a]
    forall l. IsList l => l -> [Item l]
    toList a
    a, b -> [Item b]
    forall l. IsList l => l -> [Item l]
    toList b
    b, c -> [Item c]
    forall l. IsList l => l -> [Item l]
    toList c
    c, d -> [Item d]
    forall l. IsList l => l -> [Item l]
    toList d
    d, e -> [Item e]
    forall l. IsList l => l -> [Item l]
    toList e
    e, f -> [Item f]
    forall l. IsList l => l -> [Item l]
    toList f
    f, g -> [Item g]
    forall l. IsList l => l -> [Item l]
    toList g
    g)
        where go :: (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element g
     -> Element c)
    -> (a, b, c, d, e, f, g) -> c
    go f' :: Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element g
    -> Element c
    f' = c
    -> (((Element a, Element b, Element c, Element d, Element e,
          Element f, Element g),
         (a, b, c, d, e, f, g))
        -> c)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e, Element f,
           Element g),
          (a, b, c, d, e, f, g))
    -> c
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe c
    forall a. Monoid a => a
    mempty (\(x :: (Element a, Element b, Element c, Element d, Element e, Element f,
     Element g)
    x, xs :: (a, b, c, d, e, f, g)
    xs) -> (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element g
     -> Element c)
    -> (Element a, Element b, Element c, Element d, Element e,
        Element f, Element g)
    -> Element c
    forall a b c d e f g h.
    (a -> b -> c -> d -> e -> f -> g -> h)
    -> (a, b, c, d, e, f, g) -> h
    uncurry7 Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element g
    -> Element c
    f' (Element a, Element b, Element c, Element d, Element e, Element f,
     Element g)
    x Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element g
     -> Element c)
    -> (a, b, c, d, e, f, g) -> c
    go Element a
    -> Element b
    -> Element c
    -> Element d
    -> Element e
    -> Element f
    -> Element g
    -> Element c
    f' (a, b, c, d, e, f, g)
    xs) (Maybe
       ((Element a, Element b, Element c, Element d, Element e, Element f,
         Element g),
        (a, b, c, d, e, f, g))
     -> c)
    -> ((a, b, c, d, e, f, g)
        -> Maybe
             ((Element a, Element b, Element c, Element d, Element e, Element f,
               Element g),
              (a, b, c, d, e, f, g)))
    -> (a, b, c, d, e, f, g)
    -> c
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . (a, b, c, d, e, f, g)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e, Element f,
           Element g),
          (a, b, c, d, e, f, g))
    forall a b c d e f g.
    (Sequential a, Sequential b, Sequential c, Sequential d,
     Sequential e, Sequential f, Sequential g) =>
    (a, b, c, d, e, f, g)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e, Element f,
           Element g),
          (a, b, c, d, e, f, g))
    uncons7

    instance Zippable [c]

    instance UV.PrimType ty => Zippable (UV.UArray ty) where
      zipWith :: (Element a -> Element b -> Element (UArray ty))
    -> a -> b -> UArray ty
    zipWith f :: Element a -> Element b -> Element (UArray ty)
    f as :: a
    as bs :: b
    bs = (forall s. ST s (UArray ty)) -> UArray ty
    forall a. (forall s. ST s a) -> a
    runST ((forall s. ST s (UArray ty)) -> UArray ty)
    -> (forall s. ST s (UArray ty)) -> UArray ty
    forall a b. (a -> b) -> a -> b
    $ Int
    -> Builder (UArray ty) (MUArray ty) ty (ST s) () ()
    -> ST s (UArray ty)
    forall ty (m :: * -> *).
    (PrimType ty, PrimMonad m) =>
    Int -> Builder (UArray ty) (MUArray ty) ty m () () -> m (UArray ty)
    UV.builderBuild_ 64 (Builder (UArray ty) (MUArray ty) ty (ST s) () ()
     -> ST s (UArray ty))
    -> Builder (UArray ty) (MUArray ty) ty (ST s) () ()
    -> ST s (UArray ty)
    forall a b. (a -> b) -> a -> b
    $ (Element a -> Element b -> ty)
    -> [Element a]
    -> [Element b]
    -> Builder (UArray ty) (MUArray ty) ty (ST s) () ()
    forall (state :: * -> *) ty t t err.
    (PrimType ty, PrimMonad state) =>
    (t -> t -> ty)
    -> [t] -> [t] -> Builder (UArray ty) (MUArray ty) ty state err ()
    go Element a -> Element b -> ty
    Element a -> Element b -> Element (UArray ty)
    f (a -> [Item a]
    forall l. IsList l => l -> [Item l]
    toList a
    as) (b -> [Item b]
    forall l. IsList l => l -> [Item l]
    toList b
    bs)
        where
          go :: (t -> t -> ty)
    -> [t] -> [t] -> Builder (UArray ty) (MUArray ty) ty state err ()
    go _  []       _        = () -> Builder (UArray ty) (MUArray ty) ty state err ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
          go _  _        []       = () -> Builder (UArray ty) (MUArray ty) ty state err ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
          go f' :: t -> t -> ty
    f' (a' :: t
    a':as' :: [t]
    as') (b' :: t
    b':bs' :: [t]
    bs') = ty -> Builder (UArray ty) (MUArray ty) ty state err ()
    forall ty (state :: * -> *) err.
    (PrimType ty, PrimMonad state) =>
    ty -> Builder (UArray ty) (MUArray ty) ty state err ()
    UV.builderAppend (t -> t -> ty
    f' t
    a' t
    b') Builder (UArray ty) (MUArray ty) ty state err ()
    -> Builder (UArray ty) (MUArray ty) ty state err ()
    -> Builder (UArray ty) (MUArray ty) ty state err ()
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (t -> t -> ty)
    -> [t] -> [t] -> Builder (UArray ty) (MUArray ty) ty state err ()
    go t -> t -> ty
    f' [t]
    as' [t]
    bs'

    instance Zippable (BA.Array ty) where
      zipWith :: (Element a -> Element b -> Element (Array ty))
    -> a -> b -> Array ty
    zipWith f :: Element a -> Element b -> Element (Array ty)
    f as :: a
    as bs :: b
    bs = (forall s. ST s (Array ty)) -> Array ty
    forall a. (forall s. ST s a) -> a
    runST ((forall s. ST s (Array ty)) -> Array ty)
    -> (forall s. ST s (Array ty)) -> Array ty
    forall a b. (a -> b) -> a -> b
    $ Int
    -> Builder (Array ty) (MArray ty) ty (ST s) () ()
    -> ST s (Array ty)
    forall (m :: * -> *) ty.
    PrimMonad m =>
    Int -> Builder (Array ty) (MArray ty) ty m () () -> m (Array ty)
    BA.builderBuild_ 64 (Builder (Array ty) (MArray ty) ty (ST s) () () -> ST s (Array ty))
    -> Builder (Array ty) (MArray ty) ty (ST s) () ()
    -> ST s (Array ty)
    forall a b. (a -> b) -> a -> b
    $ (Element a -> Element b -> ty)
    -> [Element a]
    -> [Element b]
    -> Builder (Array ty) (MArray ty) ty (ST s) () ()
    forall (state :: * -> *) t t ty err.
    PrimMonad state =>
    (t -> t -> ty)
    -> [t] -> [t] -> Builder (Array ty) (MArray ty) ty state err ()
    go Element a -> Element b -> ty
    Element a -> Element b -> Element (Array ty)
    f (a -> [Item a]
    forall l. IsList l => l -> [Item l]
    toList a
    as) (b -> [Item b]
    forall l. IsList l => l -> [Item l]
    toList b
    bs)
        where
          go :: (t -> t -> ty)
    -> [t] -> [t] -> Builder (Array ty) (MArray ty) ty state err ()
    go _  []       _        = () -> Builder (Array ty) (MArray ty) ty state err ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
          go _  _        []       = () -> Builder (Array ty) (MArray ty) ty state err ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
          go f' :: t -> t -> ty
    f' (a' :: t
    a':as' :: [t]
    as') (b' :: t
    b':bs' :: [t]
    bs') = ty -> Builder (Array ty) (MArray ty) ty state err ()
    forall (state :: * -> *) ty err.
    PrimMonad state =>
    ty -> Builder (Array ty) (MArray ty) ty state err ()
    BA.builderAppend (t -> t -> ty
    f' t
    a' t
    b') Builder (Array ty) (MArray ty) ty state err ()
    -> Builder (Array ty) (MArray ty) ty state err ()
    -> Builder (Array ty) (MArray ty) ty state err ()
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (t -> t -> ty)
    -> [t] -> [t] -> Builder (Array ty) (MArray ty) ty state err ()
    go t -> t -> ty
    f' [t]
    as' [t]
    bs'

    instance Zippable S.String where
      zipWith :: (Element a -> Element b -> Element String) -> a -> b -> String
    zipWith f :: Element a -> Element b -> Element String
    f as :: a
    as bs :: b
    bs = (forall s. ST s String) -> String
    forall a. (forall s. ST s a) -> a
    runST ((forall s. ST s String) -> String)
    -> (forall s. ST s String) -> String
    forall a b. (a -> b) -> a -> b
    $ Int
    -> Builder String MutableString Word8 (ST s) () () -> ST s String
    forall (m :: * -> *).
    PrimMonad m =>
    Int -> Builder String MutableString Word8 m () () -> m String
    S.builderBuild_ 64 (Builder String MutableString Word8 (ST s) () () -> ST s String)
    -> Builder String MutableString Word8 (ST s) () () -> ST s String
    forall a b. (a -> b) -> a -> b
    $ (Element a -> Element b -> Char)
    -> [Element a]
    -> [Element b]
    -> Builder String MutableString Word8 (ST s) () ()
    forall (state :: * -> *) t t err.
    PrimMonad state =>
    (t -> t -> Char)
    -> [t] -> [t] -> Builder String MutableString Word8 state err ()
    go Element a -> Element b -> Char
    Element a -> Element b -> Element String
    f (a -> [Item a]
    forall l. IsList l => l -> [Item l]
    toList a
    as) (b -> [Item b]
    forall l. IsList l => l -> [Item l]
    toList b
    bs)
        where
          go :: (t -> t -> Char)
    -> [t] -> [t] -> Builder String MutableString Word8 state err ()
    go _  []       _        = () -> Builder String MutableString Word8 state err ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
          go _  _        []       = () -> Builder String MutableString Word8 state err ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
          go f' :: t -> t -> Char
    f' (a' :: t
    a':as' :: [t]
    as') (b' :: t
    b':bs' :: [t]
    bs') = Char -> Builder String MutableString Word8 state err ()
    forall (state :: * -> *) err.
    PrimMonad state =>
    Char -> Builder String MutableString Word8 state err ()
    S.builderAppend (t -> t -> Char
    f' t
    a' t
    b') Builder String MutableString Word8 state err ()
    -> Builder String MutableString Word8 state err ()
    -> Builder String MutableString Word8 state err ()
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (t -> t -> Char)
    -> [t] -> [t] -> Builder String MutableString Word8 state err ()
    go t -> t -> Char
    f' [t]
    as' [t]
    bs'

    deriving instance Zippable AsciiString

    class Zippable col => BoxedZippable col where

      -- | 'zip' takes two collections and returns a collections of corresponding
      --   pairs. If one input collection is short, excess elements of the longer
      --   collection are discarded.
      zip :: ( Sequential a, Sequential b
             , Element col ~ (Element a, Element b) )
          => a -> b -> col
      zip = (Element a -> Element b -> Element col) -> a -> b -> col
    forall col a b.
    (Zippable col, Sequential a, Sequential b) =>
    (Element a -> Element b -> Element col) -> a -> b -> col
    zipWith (,)

      -- | Like 'zip', but works with 3 collections.
      zip3 :: ( Sequential a, Sequential b, Sequential c
              , Element col ~ (Element a, Element b, Element c) )
           => a -> b -> c -> col
      zip3 = (Element a -> Element b -> Element c -> Element col)
    -> a -> b -> c -> col
    forall col a b c.
    (Zippable col, Sequential a, Sequential b, Sequential c) =>
    (Element a -> Element b -> Element c -> Element col)
    -> a -> b -> c -> col
    zipWith3 (,,)

      -- | Like 'zip', but works with 4 collections.
      zip4 :: ( Sequential a, Sequential b, Sequential c, Sequential d
              , Element col ~ (Element a, Element b, Element c, Element d) )
           => a -> b -> c -> d -> col
      zip4 = (Element a -> Element b -> Element c -> Element d -> Element col)
    -> a -> b -> c -> d -> col
    forall col a b c d.
    (Zippable col, Sequential a, Sequential b, Sequential c,
     Sequential d) =>
    (Element a -> Element b -> Element c -> Element d -> Element col)
    -> a -> b -> c -> d -> col
    zipWith4 (,,,)

      -- | Like 'zip', but works with 5 collections.
      zip5 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e
              , Element col ~ (Element a, Element b, Element c, Element d, Element e) )
           => a -> b -> c -> d -> e -> col
      zip5 = (Element a
     -> Element b -> Element c -> Element d -> Element e -> Element col)
    -> a -> b -> c -> d -> e -> col
    forall col a b c d e.
    (Zippable col, Sequential a, Sequential b, Sequential c,
     Sequential d, Sequential e) =>
    (Element a
     -> Element b -> Element c -> Element d -> Element e -> Element col)
    -> a -> b -> c -> d -> e -> col
    zipWith5 (,,,,)

      -- | Like 'zip', but works with 6 collections.
      zip6 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e, Sequential f
              , Element col ~ (Element a, Element b, Element c, Element d, Element e, Element f) )
           => a -> b -> c -> d -> e -> f -> col
      zip6 = (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element col)
    -> a -> b -> c -> d -> e -> f -> col
    forall col a b c d e f.
    (Zippable col, Sequential a, Sequential b, Sequential c,
     Sequential d, Sequential e, Sequential f) =>
    (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element col)
    -> a -> b -> c -> d -> e -> f -> col
    zipWith6 (,,,,,)

      -- | Like 'zip', but works with 7 collections.
      zip7 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e, Sequential f, Sequential g
              , Element col ~ (Element a, Element b, Element c, Element d, Element e, Element f, Element g) )
           => a -> b -> c -> d -> e -> f -> g -> col
      zip7 = (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element g
     -> Element col)
    -> a -> b -> c -> d -> e -> f -> g -> col
    forall col a b c d e f g.
    (Zippable col, Sequential a, Sequential b, Sequential c,
     Sequential d, Sequential e, Sequential f, Sequential g) =>
    (Element a
     -> Element b
     -> Element c
     -> Element d
     -> Element e
     -> Element f
     -> Element g
     -> Element col)
    -> a -> b -> c -> d -> e -> f -> g -> col
    zipWith7 (,,,,,,)

      -- | 'unzip' transforms a collection of pairs into a collection of first
      --   components and a collection of second components.
      unzip :: (Sequential a, Sequential b, Element col ~ (Element a, Element b))
            => col -> (a, b)
      unzip = [(Element a, Element b)] -> (a, b)
    forall a b.
    (Sequential a, Sequential b) =>
    [(Element a, Element b)] -> (a, b)
    go ([(Element a, Element b)] -> (a, b))
    -> (col -> [(Element a, Element b)]) -> col -> (a, b)
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . col -> [(Element a, Element b)]
    forall l. IsList l => l -> [Item l]
    toList
        where go :: [(Element a, Element b)] -> (a, b)
    go []          = (a
    forall a. Monoid a => a
    mempty, b
    forall a. Monoid a => a
    mempty)
              go ((a :: Element a
    a, b :: Element b
    b):xs :: [(Element a, Element b)]
    xs) =
                  let (as :: a
    as, bs :: b
    bs) = [(Element a, Element b)] -> (a, b)
    go [(Element a, Element b)]
    xs
                  in (Element a
    a Element a -> a -> a
    forall c. Sequential c => Element c -> c -> c
    `cons` a
    as, Element b
    b Element b -> b -> b
    forall c. Sequential c => Element c -> c -> c
    `cons` b
    bs)

      -- | Like 'unzip', but works on a collection of 3-element tuples.
      unzip3 :: ( Sequential a, Sequential b, Sequential c
                , Element col ~ (Element a, Element b, Element c) )
             => col -> (a, b, c)
      unzip3 = [(Element a, Element b, Element c)] -> (a, b, c)
    forall a b c.
    (Sequential a, Sequential b, Sequential c) =>
    [(Element a, Element b, Element c)] -> (a, b, c)
    go ([(Element a, Element b, Element c)] -> (a, b, c))
    -> (col -> [(Element a, Element b, Element c)]) -> col -> (a, b, c)
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . col -> [(Element a, Element b, Element c)]
    forall l. IsList l => l -> [Item l]
    toList
        where go :: [(Element a, Element b, Element c)] -> (a, b, c)
    go [] = (a
    forall a. Monoid a => a
    mempty, b
    forall a. Monoid a => a
    mempty, c
    forall a. Monoid a => a
    mempty)
              go ((a :: Element a
    a, b :: Element b
    b, c :: Element c
    c):xs :: [(Element a, Element b, Element c)]
    xs) =
                  let (as :: a
    as, bs :: b
    bs, cs :: c
    cs) = [(Element a, Element b, Element c)] -> (a, b, c)
    go [(Element a, Element b, Element c)]
    xs
                  in (Element a
    a Element a -> a -> a
    forall c. Sequential c => Element c -> c -> c
    `cons` a
    as, Element b
    b Element b -> b -> b
    forall c. Sequential c => Element c -> c -> c
    `cons` b
    bs, Element c
    c Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` c
    cs)

      -- | Like 'unzip', but works on a collection of 4-element tuples.
      unzip4 :: ( Sequential a, Sequential b, Sequential c, Sequential d
                , Element col ~ (Element a, Element b, Element c, Element d) )
             => col -> (a, b, c, d)
      unzip4 = [(Element a, Element b, Element c, Element d)] -> (a, b, c, d)
    forall a b c d.
    (Sequential a, Sequential b, Sequential c, Sequential d) =>
    [(Element a, Element b, Element c, Element d)] -> (a, b, c, d)
    go ([(Element a, Element b, Element c, Element d)] -> (a, b, c, d))
    -> (col -> [(Element a, Element b, Element c, Element d)])
    -> col
    -> (a, b, c, d)
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . col -> [(Element a, Element b, Element c, Element d)]
    forall l. IsList l => l -> [Item l]
    toList
        where go :: [(Element a, Element b, Element c, Element d)] -> (a, b, c, d)
    go [] = (a
    forall a. Monoid a => a
    mempty, b
    forall a. Monoid a => a
    mempty, c
    forall a. Monoid a => a
    mempty, d
    forall a. Monoid a => a
    mempty)
              go ((a :: Element a
    a, b :: Element b
    b, c :: Element c
    c, d :: Element d
    d):xs :: [(Element a, Element b, Element c, Element d)]
    xs) =
                  let (as :: a
    as, bs :: b
    bs, cs :: c
    cs, ds :: d
    ds) = [(Element a, Element b, Element c, Element d)] -> (a, b, c, d)
    go [(Element a, Element b, Element c, Element d)]
    xs
                  in (Element a
    a Element a -> a -> a
    forall c. Sequential c => Element c -> c -> c
    `cons` a
    as, Element b
    b Element b -> b -> b
    forall c. Sequential c => Element c -> c -> c
    `cons` b
    bs, Element c
    c Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` c
    cs, Element d
    d Element d -> d -> d
    forall c. Sequential c => Element c -> c -> c
    `cons` d
    ds)

      -- | Like 'unzip', but works on a collection of 5-element tuples.
      unzip5 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e
                , Element col ~ (Element a, Element b, Element c, Element d, Element e) )
             => col -> (a, b, c, d, e)
      unzip5 = [(Element a, Element b, Element c, Element d, Element e)]
    -> (a, b, c, d, e)
    forall a b c d e.
    (Sequential a, Sequential b, Sequential c, Sequential d,
     Sequential e) =>
    [(Element a, Element b, Element c, Element d, Element e)]
    -> (a, b, c, d, e)
    go ([(Element a, Element b, Element c, Element d, Element e)]
     -> (a, b, c, d, e))
    -> (col
        -> [(Element a, Element b, Element c, Element d, Element e)])
    -> col
    -> (a, b, c, d, e)
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . col -> [(Element a, Element b, Element c, Element d, Element e)]
    forall l. IsList l => l -> [Item l]
    toList
        where go :: [(Element a, Element b, Element c, Element d, Element e)]
    -> (a, b, c, d, e)
    go [] = (a
    forall a. Monoid a => a
    mempty, b
    forall a. Monoid a => a
    mempty, c
    forall a. Monoid a => a
    mempty, d
    forall a. Monoid a => a
    mempty, e
    forall a. Monoid a => a
    mempty)
              go ((a :: Element a
    a, b :: Element b
    b, c :: Element c
    c, d :: Element d
    d, e :: Element e
    e):xs :: [(Element a, Element b, Element c, Element d, Element e)]
    xs) =
                  let (as :: a
    as, bs :: b
    bs, cs :: c
    cs, ds :: d
    ds, es :: e
    es) = [(Element a, Element b, Element c, Element d, Element e)]
    -> (a, b, c, d, e)
    go [(Element a, Element b, Element c, Element d, Element e)]
    xs
                  in (Element a
    a Element a -> a -> a
    forall c. Sequential c => Element c -> c -> c
    `cons` a
    as, Element b
    b Element b -> b -> b
    forall c. Sequential c => Element c -> c -> c
    `cons` b
    bs, Element c
    c Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` c
    cs, Element d
    d Element d -> d -> d
    forall c. Sequential c => Element c -> c -> c
    `cons` d
    ds, Element e
    e Element e -> e -> e
    forall c. Sequential c => Element c -> c -> c
    `cons` e
    es)

      -- | Like 'unzip', but works on a collection of 6-element tuples.
      unzip6 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e, Sequential f
                , Element col ~ (Element a, Element b, Element c, Element d, Element e, Element f) )
             => col -> (a, b, c, d, e, f)
      unzip6 = [(Element a, Element b, Element c, Element d, Element e,
      Element f)]
    -> (a, b, c, d, e, f)
    forall a b c d e f.
    (Sequential a, Sequential b, Sequential c, Sequential d,
     Sequential e, Sequential f) =>
    [(Element a, Element b, Element c, Element d, Element e,
      Element f)]
    -> (a, b, c, d, e, f)
    go ([(Element a, Element b, Element c, Element d, Element e,
       Element f)]
     -> (a, b, c, d, e, f))
    -> (col
        -> [(Element a, Element b, Element c, Element d, Element e,
             Element f)])
    -> col
    -> (a, b, c, d, e, f)
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . col
    -> [(Element a, Element b, Element c, Element d, Element e,
         Element f)]
    forall l. IsList l => l -> [Item l]
    toList
        where go :: [(Element a, Element b, Element c, Element d, Element e,
      Element f)]
    -> (a, b, c, d, e, f)
    go [] = (a
    forall a. Monoid a => a
    mempty, b
    forall a. Monoid a => a
    mempty, c
    forall a. Monoid a => a
    mempty, d
    forall a. Monoid a => a
    mempty, e
    forall a. Monoid a => a
    mempty, f
    forall a. Monoid a => a
    mempty)
              go ((a :: Element a
    a, b :: Element b
    b, c :: Element c
    c, d :: Element d
    d, e :: Element e
    e, f :: Element f
    f):xs :: [(Element a, Element b, Element c, Element d, Element e,
      Element f)]
    xs) =
                  let (as :: a
    as, bs :: b
    bs, cs :: c
    cs, ds :: d
    ds, es :: e
    es, fs :: f
    fs) = [(Element a, Element b, Element c, Element d, Element e,
      Element f)]
    -> (a, b, c, d, e, f)
    go [(Element a, Element b, Element c, Element d, Element e,
      Element f)]
    xs
                  in (Element a
    a Element a -> a -> a
    forall c. Sequential c => Element c -> c -> c
    `cons` a
    as, Element b
    b Element b -> b -> b
    forall c. Sequential c => Element c -> c -> c
    `cons` b
    bs, Element c
    c Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` c
    cs, Element d
    d Element d -> d -> d
    forall c. Sequential c => Element c -> c -> c
    `cons` d
    ds, Element e
    e Element e -> e -> e
    forall c. Sequential c => Element c -> c -> c
    `cons` e
    es, Element f
    f Element f -> f -> f
    forall c. Sequential c => Element c -> c -> c
    `cons` f
    fs)

      -- | Like 'unzip', but works on a collection of 7-element tuples.
      unzip7 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e, Sequential f, Sequential g
                , Element col ~ (Element a, Element b, Element c, Element d, Element e, Element f, Element g) )
            => col -> (a, b, c, d, e, f, g)
      unzip7 = [(Element a, Element b, Element c, Element d, Element e, Element f,
      Element g)]
    -> (a, b, c, d, e, f, g)
    forall a b c d e f g.
    (Sequential a, Sequential b, Sequential c, Sequential d,
     Sequential e, Sequential f, Sequential g) =>
    [(Element a, Element b, Element c, Element d, Element e, Element f,
      Element g)]
    -> (a, b, c, d, e, f, g)
    go ([(Element a, Element b, Element c, Element d, Element e,
       Element f, Element g)]
     -> (a, b, c, d, e, f, g))
    -> (col
        -> [(Element a, Element b, Element c, Element d, Element e,
             Element f, Element g)])
    -> col
    -> (a, b, c, d, e, f, g)
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . col
    -> [(Element a, Element b, Element c, Element d, Element e,
         Element f, Element g)]
    forall l. IsList l => l -> [Item l]
    toList
        where go :: [(Element a, Element b, Element c, Element d, Element e, Element f,
      Element g)]
    -> (a, b, c, d, e, f, g)
    go [] = (a
    forall a. Monoid a => a
    mempty, b
    forall a. Monoid a => a
    mempty, c
    forall a. Monoid a => a
    mempty, d
    forall a. Monoid a => a
    mempty, e
    forall a. Monoid a => a
    mempty, f
    forall a. Monoid a => a
    mempty, g
    forall a. Monoid a => a
    mempty)
              go ((a :: Element a
    a, b :: Element b
    b, c :: Element c
    c, d :: Element d
    d, e :: Element e
    e, f :: Element f
    f, g :: Element g
    g):xs :: [(Element a, Element b, Element c, Element d, Element e, Element f,
      Element g)]
    xs) =
                  let (as :: a
    as, bs :: b
    bs, cs :: c
    cs, ds :: d
    ds, es :: e
    es, fs :: f
    fs, gs :: g
    gs) = [(Element a, Element b, Element c, Element d, Element e, Element f,
      Element g)]
    -> (a, b, c, d, e, f, g)
    go [(Element a, Element b, Element c, Element d, Element e, Element f,
      Element g)]
    xs
                  in (Element a
    a Element a -> a -> a
    forall c. Sequential c => Element c -> c -> c
    `cons` a
    as, Element b
    b Element b -> b -> b
    forall c. Sequential c => Element c -> c -> c
    `cons` b
    bs, Element c
    c Element c -> c -> c
    forall c. Sequential c => Element c -> c -> c
    `cons` c
    cs, Element d
    d Element d -> d -> d
    forall c. Sequential c => Element c -> c -> c
    `cons` d
    ds, Element e
    e Element e -> e -> e
    forall c. Sequential c => Element c -> c -> c
    `cons` e
    es, Element f
    f Element f -> f -> f
    forall c. Sequential c => Element c -> c -> c
    `cons` f
    fs, Element g
    g Element g -> g -> g
    forall c. Sequential c => Element c -> c -> c
    `cons` g
    gs)

    instance BoxedZippable [a]
    instance BoxedZippable (BA.Array ty)

    -- * Tuple helper functions

    uncons2 :: (Sequential a, Sequential b) => (a, b) -> Maybe ((Element a, Element b), (a, b))
    uncons2 :: (a, b) -> Maybe ((Element a, Element b), (a, b))
    uncons2 xs :: (a, b)
    xs = let (as :: a
    as, bs :: b
    bs) = (a, b)
    xs
                 in do (a' :: Element a
    a', as' :: a
    as') <- a -> Maybe (Element a, a)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons a
    as
                       (b' :: Element b
    b', bs' :: b
    bs') <- b -> Maybe (Element b, b)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons b
    bs
                       ((Element a, Element b), (a, b))
    -> Maybe ((Element a, Element b), (a, b))
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((Element a
    a', Element b
    b'), (a
    as', b
    bs'))

    uncons3 :: (Sequential a, Sequential b, Sequential c)
            => (a, b, c)
            -> Maybe ((Element a, Element b, Element c), (a, b, c))
    uncons3 :: (a, b, c) -> Maybe ((Element a, Element b, Element c), (a, b, c))
    uncons3 xs :: (a, b, c)
    xs = let (as :: a
    as, bs :: b
    bs, cs :: c
    cs) = (a, b, c)
    xs
                 in do (a' :: Element a
    a', as' :: a
    as') <- a -> Maybe (Element a, a)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons a
    as
                       (b' :: Element b
    b', bs' :: b
    bs') <- b -> Maybe (Element b, b)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons b
    bs
                       (c' :: Element c
    c', cs' :: c
    cs') <- c -> Maybe (Element c, c)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons c
    cs
                       ((Element a, Element b, Element c), (a, b, c))
    -> Maybe ((Element a, Element b, Element c), (a, b, c))
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((Element a
    a', Element b
    b', Element c
    c'), (a
    as', b
    bs', c
    cs'))

    uncons4 :: (Sequential a, Sequential b, Sequential c, Sequential d)
            => (a, b, c, d)
            -> Maybe ( (Element a, Element b, Element c, Element d)
                     , (a, b, c, d) )
    uncons4 :: (a, b, c, d)
    -> Maybe
         ((Element a, Element b, Element c, Element d), (a, b, c, d))
    uncons4 xs :: (a, b, c, d)
    xs = let (as :: a
    as, bs :: b
    bs, cs :: c
    cs, ds :: d
    ds) = (a, b, c, d)
    xs
                 in do (a' :: Element a
    a', as' :: a
    as') <- a -> Maybe (Element a, a)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons a
    as
                       (b' :: Element b
    b', bs' :: b
    bs') <- b -> Maybe (Element b, b)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons b
    bs
                       (c' :: Element c
    c', cs' :: c
    cs') <- c -> Maybe (Element c, c)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons c
    cs
                       (d' :: Element d
    d', ds' :: d
    ds') <- d -> Maybe (Element d, d)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons d
    ds
                       ((Element a, Element b, Element c, Element d), (a, b, c, d))
    -> Maybe
         ((Element a, Element b, Element c, Element d), (a, b, c, d))
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((Element a
    a', Element b
    b', Element c
    c', Element d
    d'), (a
    as', b
    bs', c
    cs', d
    ds'))

    uncons5 :: (Sequential a, Sequential b, Sequential c, Sequential d, Sequential e)
            => (a, b, c, d, e)
            -> Maybe ( (Element a, Element b, Element c, Element d, Element e)
                     , (a, b, c, d, e) )
    uncons5 :: (a, b, c, d, e)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e),
          (a, b, c, d, e))
    uncons5 xs :: (a, b, c, d, e)
    xs = let (as :: a
    as, bs :: b
    bs, cs :: c
    cs, ds :: d
    ds, es :: e
    es) = (a, b, c, d, e)
    xs
                 in do (a' :: Element a
    a', as' :: a
    as') <- a -> Maybe (Element a, a)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons a
    as
                       (b' :: Element b
    b', bs' :: b
    bs') <- b -> Maybe (Element b, b)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons b
    bs
                       (c' :: Element c
    c', cs' :: c
    cs') <- c -> Maybe (Element c, c)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons c
    cs
                       (d' :: Element d
    d', ds' :: d
    ds') <- d -> Maybe (Element d, d)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons d
    ds
                       (e' :: Element e
    e', es' :: e
    es') <- e -> Maybe (Element e, e)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons e
    es
                       ((Element a, Element b, Element c, Element d, Element e),
     (a, b, c, d, e))
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e),
          (a, b, c, d, e))
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((Element a
    a', Element b
    b', Element c
    c', Element d
    d', Element e
    e'), (a
    as', b
    bs', c
    cs', d
    ds', e
    es'))

    uncons6 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e
               , Sequential f )
            => (a, b, c, d, e, f)
            -> Maybe ( (Element a, Element b, Element c, Element d, Element e, Element f)
                     , (a, b, c, d, e, f) )
    uncons6 :: (a, b, c, d, e, f)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e,
           Element f),
          (a, b, c, d, e, f))
    uncons6 xs :: (a, b, c, d, e, f)
    xs = let (as :: a
    as, bs :: b
    bs, cs :: c
    cs, ds :: d
    ds, es :: e
    es, fs :: f
    fs) = (a, b, c, d, e, f)
    xs
                 in do (a' :: Element a
    a', as' :: a
    as') <- a -> Maybe (Element a, a)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons a
    as
                       (b' :: Element b
    b', bs' :: b
    bs') <- b -> Maybe (Element b, b)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons b
    bs
                       (c' :: Element c
    c', cs' :: c
    cs') <- c -> Maybe (Element c, c)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons c
    cs
                       (d' :: Element d
    d', ds' :: d
    ds') <- d -> Maybe (Element d, d)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons d
    ds
                       (e' :: Element e
    e', es' :: e
    es') <- e -> Maybe (Element e, e)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons e
    es
                       (f' :: Element f
    f', fs' :: f
    fs') <- f -> Maybe (Element f, f)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons f
    fs
                       ((Element a, Element b, Element c, Element d, Element e,
      Element f),
     (a, b, c, d, e, f))
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e,
           Element f),
          (a, b, c, d, e, f))
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((Element a
    a', Element b
    b', Element c
    c', Element d
    d', Element e
    e', Element f
    f'), (a
    as', b
    bs', c
    cs', d
    ds', e
    es', f
    fs'))

    uncons7 :: ( Sequential a, Sequential b, Sequential c, Sequential d, Sequential e
               , Sequential f, Sequential g )
            => (a, b, c, d, e, f, g)
            -> Maybe ( (Element a, Element b, Element c, Element d, Element e, Element f
                     , Element g)
                     , (a, b, c, d, e, f, g) )
    uncons7 :: (a, b, c, d, e, f, g)
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e, Element f,
           Element g),
          (a, b, c, d, e, f, g))
    uncons7 xs :: (a, b, c, d, e, f, g)
    xs = let (as :: a
    as, bs :: b
    bs, cs :: c
    cs, ds :: d
    ds, es :: e
    es, fs :: f
    fs, gs :: g
    gs) = (a, b, c, d, e, f, g)
    xs
                 in do (a' :: Element a
    a', as' :: a
    as') <- a -> Maybe (Element a, a)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons a
    as
                       (b' :: Element b
    b', bs' :: b
    bs') <- b -> Maybe (Element b, b)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons b
    bs
                       (c' :: Element c
    c', cs' :: c
    cs') <- c -> Maybe (Element c, c)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons c
    cs
                       (d' :: Element d
    d', ds' :: d
    ds') <- d -> Maybe (Element d, d)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons d
    ds
                       (e' :: Element e
    e', es' :: e
    es') <- e -> Maybe (Element e, e)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons e
    es
                       (f' :: Element f
    f', fs' :: f
    fs') <- f -> Maybe (Element f, f)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons f
    fs
                       (g' :: Element g
    g', gs' :: g
    gs') <- g -> Maybe (Element g, g)
    forall c. Sequential c => c -> Maybe (Element c, c)
    uncons g
    gs
                       ((Element a, Element b, Element c, Element d, Element e, Element f,
      Element g),
     (a, b, c, d, e, f, g))
    -> Maybe
         ((Element a, Element b, Element c, Element d, Element e, Element f,
           Element g),
          (a, b, c, d, e, f, g))
    forall (m :: * -> *) a. Monad m => a -> m a
    return ( (Element a
    a', Element b
    b', Element c
    c', Element d
    d', Element e
    e', Element f
    f', Element g
    g')
                              , (a
    as', b
    bs', c
    cs', d
    ds', e
    es', f
    fs', g
    gs') )

    uncurry2 :: (a -> b -> c) -> (a, b) -> c
    uncurry2 :: (a -> b -> c) -> (a, b) -> c
    uncurry2 = (a -> b -> c) -> (a, b) -> c
    forall a b c. (a -> b -> c) -> (a, b) -> c
    Prelude.uncurry

    uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
    uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
    uncurry3 fn :: a -> b -> c -> d
    fn (a :: a
    a, b :: b
    b, c :: c
    c) = a -> b -> c -> d
    fn a
    a b
    b c
    c

    uncurry4 :: (a -> b -> c -> d -> g) -> (a, b, c, d) -> g
    uncurry4 :: (a -> b -> c -> d -> g) -> (a, b, c, d) -> g
    uncurry4 fn :: a -> b -> c -> d -> g
    fn (a :: a
    a, b :: b
    b, c :: c
    c, d :: d
    d) = a -> b -> c -> d -> g
    fn a
    a b
    b c
    c d
    d

    uncurry5 :: (a -> b -> c -> d -> e -> f) -> (a, b, c, d, e) -> f
    uncurry5 :: (a -> b -> c -> d -> e -> f) -> (a, b, c, d, e) -> f
    uncurry5 fn :: a -> b -> c -> d -> e -> f
    fn (a :: a
    a, b :: b
    b, c :: c
    c, d :: d
    d, e :: e
    e) = a -> b -> c -> d -> e -> f
    fn a
    a b
    b c
    c d
    d e
    e

    uncurry6 :: (a -> b -> c -> d -> e -> f -> g) -> (a, b, c, d, e, f) -> g
    uncurry6 :: (a -> b -> c -> d -> e -> f -> g) -> (a, b, c, d, e, f) -> g
    uncurry6 fn :: a -> b -> c -> d -> e -> f -> g
    fn (a :: a
    a, b :: b
    b, c :: c
    c, d :: d
    d, e :: e
    e, f :: f
    f) = a -> b -> c -> d -> e -> f -> g
    fn a
    a b
    b c
    c d
    d e
    e f
    f

    uncurry7 :: (a -> b -> c -> d -> e -> f -> g -> h) -> (a, b, c, d, e, f, g) -> h
    uncurry7 :: (a -> b -> c -> d -> e -> f -> g -> h)
    -> (a, b, c, d, e, f, g) -> h
    uncurry7 fn :: a -> b -> c -> d -> e -> f -> g -> h
    fn (a :: a
    a, b :: b
    b, c :: c
    c, d :: d
    d, e :: e
    e, f :: f
    f, g :: g
    g) = a -> b -> c -> d -> e -> f -> g -> h
    fn a
    a b
    b c
    c d
    d e
    e f
    f g
    g