-- |
-- Copyright:   (c) 2022 Bodigrim
-- License:     BSD3
module Data.List.Infinite.Zip (
  zip,
  zipWith,
  zip3,
  zipWith3,
  zip4,
  zipWith4,
  zip5,
  zipWith5,
  zip6,
  zipWith6,
  zip7,
  zipWith7,
) where

import Prelude (flip, (.))

import Data.List.Infinite.Internal

-- | Zip two infinite lists.
zip :: Infinite a -> Infinite b -> Infinite (a, b)
zip = zipWith (,)
{-# INLINE zip #-}

-- | Zip two infinite lists with a given function.
zipWith :: (a -> b -> c) -> Infinite a -> Infinite b -> Infinite c
zipWith fun = go
  where
    go (a :< as) (b :< bs) = fun a b :< go as bs

zipWithFB :: (elt -> lst -> lst') -> (a -> b -> elt) -> a -> b -> lst -> lst'
zipWithFB = (.) . (.)

{-# NOINLINE [1] zipWith #-}

{-# INLINE [0] zipWithFB #-}

{-# RULES
"zipWith" [~1] forall f xs ys.
  zipWith f xs ys =
    build (\cons -> foldr2 (zipWithFB cons f) xs ys)
"zipWithList" [1] forall f.
  foldr2 (zipWithFB (:<) f) =
    zipWith f
  #-}

foldr2 :: (elt1 -> elt2 -> lst -> lst) -> Infinite elt1 -> Infinite elt2 -> lst
foldr2 cons = go
  where
    go (a :< as) (b :< bs) = cons a b (go as bs)
{-# INLINE [0] foldr2 #-}

foldr2_left :: (elt1 -> elt2 -> lst -> lst') -> elt1 -> (Infinite elt2 -> lst) -> Infinite elt2 -> lst'
foldr2_left cons a r (b :< bs) = cons a b (r bs)

{-# RULES
"foldr2/1" forall (cons :: elt1 -> elt2 -> lst -> lst) (bs :: Infinite elt2) (g :: forall b. (elt1 -> b -> b) -> b).
  foldr2 cons (build g) bs =
    g (foldr2_left cons) bs
"foldr2/2" forall (cons :: elt1 -> elt2 -> lst -> lst) (as :: Infinite elt1) (g :: forall b. (elt2 -> b -> b) -> b).
  foldr2 cons as (build g) =
    g (foldr2_left (flip cons)) as
  #-}

-- | Zip three infinite lists.
zip3 :: Infinite a -> Infinite b -> Infinite c -> Infinite (a, b, c)
zip3 = zipWith3 (,,)
{-# INLINE zip3 #-}

-- | Zip three infinite lists with a given function.
zipWith3 :: (a -> b -> c -> d) -> Infinite a -> Infinite b -> Infinite c -> Infinite d
zipWith3 fun = go
  where
    go (a :< as) (b :< bs) (c :< cs) = fun a b c :< go as bs cs

zipWith3FB :: (elt -> lst -> lst') -> (a -> b -> c -> elt) -> a -> b -> c -> lst -> lst'
zipWith3FB = (.) . (.) . (.)

{-# NOINLINE [1] zipWith3 #-}

{-# INLINE [0] zipWith3FB #-}

{-# RULES
"zipWith3" [~1] forall f xs ys zs.
  zipWith3 f xs ys zs =
    build (\cons -> foldr3 (zipWith3FB cons f) xs ys zs)
"zipWith3List" [1] forall f.
  foldr3 (zipWith3FB (:<) f) =
    zipWith3 f
  #-}

foldr3 :: (elt1 -> elt2 -> elt3 -> lst -> lst) -> Infinite elt1 -> Infinite elt2 -> Infinite elt3 -> lst
foldr3 cons = go
  where
    go (a :< as) (b :< bs) (c :< cs) = cons a b c (go as bs cs)
{-# INLINE [0] foldr3 #-}

foldr3_left :: (elt1 -> elt2 -> elt3 -> lst -> lst') -> elt1 -> (Infinite elt2 -> Infinite elt3 -> lst) -> Infinite elt2 -> Infinite elt3 -> lst'
foldr3_left cons a r (b :< bs) (c :< cs) = cons a b c (r bs cs)

{-# RULES
"foldr3/1" forall (cons :: elt1 -> elt2 -> elt3 -> lst -> lst) (bs :: Infinite elt2) (cs :: Infinite elt3) (g :: forall b. (elt1 -> b -> b) -> b).
  foldr3 cons (build g) bs cs =
    g (foldr3_left cons) bs cs
"foldr3/2" forall (cons :: elt1 -> elt2 -> elt3 -> lst -> lst) (as :: Infinite elt1) (cs :: Infinite elt3) (g :: forall b. (elt2 -> b -> b) -> b).
  foldr3 cons as (build g) cs =
    g (foldr3_left (flip cons)) as cs
"foldr3/3" forall (cons :: elt1 -> elt2 -> elt3 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (g :: forall b. (elt3 -> b -> b) -> b).
  foldr3 cons as bs (build g) =
    g (foldr3_left (\c a b -> cons a b c)) as bs
  #-}

-- | Zip four infinite lists.
zip4 :: Infinite a -> Infinite b -> Infinite c -> Infinite d -> Infinite (a, b, c, d)
zip4 = zipWith4 (,,,)
{-# INLINE zip4 #-}

-- | Zip four infinite lists with a given function.
zipWith4 :: (a -> b -> c -> d -> e) -> Infinite a -> Infinite b -> Infinite c -> Infinite d -> Infinite e
zipWith4 fun = go
  where
    go (a :< as) (b :< bs) (c :< cs) (d :< ds) = fun a b c d :< go as bs cs ds

zipWith4FB :: (elt -> lst -> lst') -> (a -> b -> c -> d -> elt) -> a -> b -> c -> d -> lst -> lst'
zipWith4FB = (.) . (.) . (.) . (.)

{-# NOINLINE [1] zipWith4 #-}

{-# INLINE [0] zipWith4FB #-}

{-# RULES
"zipWith4" [~1] forall f xs ys zs ts.
  zipWith4 f xs ys zs ts =
    build (\cons -> foldr4 (zipWith4FB cons f) xs ys zs ts)
"zipWith4List" [1] forall f.
  foldr4 (zipWith4FB (:<) f) =
    zipWith4 f
  #-}

foldr4 :: (elt1 -> elt2 -> elt3 -> elt4 -> lst -> lst) -> Infinite elt1 -> Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> lst
foldr4 cons = go
  where
    go (a :< as) (b :< bs) (c :< cs) (d :< ds) = cons a b c d (go as bs cs ds)
{-# INLINE [0] foldr4 #-}

foldr4_left :: (elt1 -> elt2 -> elt3 -> elt4 -> lst -> lst') -> elt1 -> (Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> lst) -> Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> lst'
foldr4_left cons a r (b :< bs) (c :< cs) (d :< ds) = cons a b c d (r bs cs ds)

{-# RULES
"foldr4/1" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> lst -> lst) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (g :: forall b. (elt1 -> b -> b) -> b).
  foldr4 cons (build g) bs cs ds =
    g (foldr4_left cons) bs cs ds
"foldr4/2" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> lst -> lst) (as :: Infinite elt1) (cs :: Infinite elt3) (ds :: Infinite elt4) (g :: forall b. (elt2 -> b -> b) -> b).
  foldr4 cons as (build g) cs ds =
    g (foldr4_left (flip cons)) as cs ds
"foldr4/3" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (ds :: Infinite elt4) (g :: forall b. (elt3 -> b -> b) -> b).
  foldr4 cons as bs (build g) ds =
    g (foldr4_left (\c a b d -> cons a b c d)) as bs ds
"foldr4/4" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (g :: forall b. (elt4 -> b -> b) -> b).
  foldr4 cons as bs cs (build g) =
    g (foldr4_left (\d a b c -> cons a b c d)) as bs cs
  #-}

-- | Zip five infinite lists.
zip5 :: Infinite a -> Infinite b -> Infinite c -> Infinite d -> Infinite e -> Infinite (a, b, c, d, e)
zip5 = zipWith5 (,,,,)
{-# INLINE zip5 #-}

-- | Zip five infinite lists with a given function.
zipWith5 :: (a -> b -> c -> d -> e -> f) -> Infinite a -> Infinite b -> Infinite c -> Infinite d -> Infinite e -> Infinite f
zipWith5 fun = go
  where
    go (a :< as) (b :< bs) (c :< cs) (d :< ds) (e :< es) = fun a b c d e :< go as bs cs ds es

zipWith5FB :: (elt -> lst -> lst') -> (a -> b -> c -> d -> e -> elt) -> a -> b -> c -> d -> e -> lst -> lst'
zipWith5FB = (.) . (.) . (.) . (.) . (.)

{-# NOINLINE [1] zipWith5 #-}

{-# INLINE [0] zipWith5FB #-}

{-# RULES
"zipWith5" [~1] forall f xs ys zs ts us.
  zipWith5 f xs ys zs ts us =
    build (\cons -> foldr5 (zipWith5FB cons f) xs ys zs ts us)
"zipWith5List" [1] forall f.
  foldr5 (zipWith5FB (:<) f) =
    zipWith5 f
  #-}

foldr5 :: (elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> lst -> lst) -> Infinite elt1 -> Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> Infinite elt5 -> lst
foldr5 cons = go
  where
    go (a :< as) (b :< bs) (c :< cs) (d :< ds) (e :< es) = cons a b c d e (go as bs cs ds es)
{-# INLINE [0] foldr5 #-}

foldr5_left :: (elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> lst -> lst') -> elt1 -> (Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> Infinite elt5 -> lst) -> Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> Infinite elt5 -> lst'
foldr5_left cons a r (b :< bs) (c :< cs) (d :< ds) (e :< es) = cons a b c d e (r bs cs ds es)

{-# RULES
"foldr5/1" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> lst -> lst) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (es :: Infinite elt5) (g :: forall b. (elt1 -> b -> b) -> b).
  foldr5 cons (build g) bs cs ds es =
    g (foldr5_left cons) bs cs ds es
"foldr5/2" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> lst -> lst) (as :: Infinite elt1) (cs :: Infinite elt3) (ds :: Infinite elt4) (es :: Infinite elt5) (g :: forall b. (elt2 -> b -> b) -> b).
  foldr5 cons as (build g) cs ds es =
    g (foldr5_left (flip cons)) as cs ds es
"foldr5/3" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (ds :: Infinite elt4) (es :: Infinite elt5) (g :: forall b. (elt3 -> b -> b) -> b).
  foldr5 cons as bs (build g) ds es =
    g (foldr5_left (\c a b d e -> cons a b c d e)) as bs ds es
"foldr5/4" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (es :: Infinite elt5) (g :: forall b. (elt4 -> b -> b) -> b).
  foldr5 cons as bs cs (build g) es =
    g (foldr5_left (\d a b c e -> cons a b c d e)) as bs cs es
"foldr5/5" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (g :: forall b. (elt5 -> b -> b) -> b).
  foldr5 cons as bs cs ds (build g) =
    g (foldr5_left (\e a b c d -> cons a b c d e)) as bs cs ds
  #-}

-- | Zip six infinite lists.
zip6 :: Infinite a -> Infinite b -> Infinite c -> Infinite d -> Infinite e -> Infinite f -> Infinite (a, b, c, d, e, f)
zip6 = zipWith6 (,,,,,)
{-# INLINE zip6 #-}

-- | Zip six infinite lists with a given function.
zipWith6 :: (a -> b -> c -> d -> e -> f -> g) -> Infinite a -> Infinite b -> Infinite c -> Infinite d -> Infinite e -> Infinite f -> Infinite g
zipWith6 fun = go
  where
    go (a :< as) (b :< bs) (c :< cs) (d :< ds) (e :< es) (f :< fs) = fun a b c d e f :< go as bs cs ds es fs

zipWith6FB :: (elt -> lst -> lst') -> (a -> b -> c -> d -> e -> f -> elt) -> a -> b -> c -> d -> e -> f -> lst -> lst'
zipWith6FB = (.) . (.) . (.) . (.) . (.) . (.)

{-# NOINLINE [1] zipWith6 #-}

{-# INLINE [0] zipWith6FB #-}

{-# RULES
"zipWith6" [~1] forall f xs ys zs ts us vs.
  zipWith6 f xs ys zs ts us vs =
    build (\cons -> foldr6 (zipWith6FB cons f) xs ys zs ts us vs)
"zipWith6List" [1] forall f.
  foldr6 (zipWith6FB (:<) f) =
    zipWith6 f
  #-}

foldr6 :: (elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> lst -> lst) -> Infinite elt1 -> Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> Infinite elt5 -> Infinite elt6 -> lst
foldr6 cons = go
  where
    go (a :< as) (b :< bs) (c :< cs) (d :< ds) (e :< es) (f :< fs) = cons a b c d e f (go as bs cs ds es fs)
{-# INLINE [0] foldr6 #-}

foldr6_left :: (elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> lst -> lst') -> elt1 -> (Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> Infinite elt5 -> Infinite elt6 -> lst) -> Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> Infinite elt5 -> Infinite elt6 -> lst'
foldr6_left cons a r (b :< bs) (c :< cs) (d :< ds) (e :< es) (f :< fs) = cons a b c d e f (r bs cs ds es fs)

{-# RULES
"foldr6/1" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> lst -> lst) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (es :: Infinite elt5) (fs :: Infinite elt6) (g :: forall b. (elt1 -> b -> b) -> b).
  foldr6 cons (build g) bs cs ds es fs =
    g (foldr6_left cons) bs cs ds es fs
"foldr6/2" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> lst -> lst) (as :: Infinite elt1) (cs :: Infinite elt3) (ds :: Infinite elt4) (es :: Infinite elt5) (fs :: Infinite elt6) (g :: forall b. (elt2 -> b -> b) -> b).
  foldr6 cons as (build g) cs ds es fs =
    g (foldr6_left (flip cons)) as cs ds es fs
"foldr6/3" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (ds :: Infinite elt4) (es :: Infinite elt5) (fs :: Infinite elt6) (g :: forall b. (elt3 -> b -> b) -> b).
  foldr6 cons as bs (build g) ds es fs =
    g (foldr6_left (\c a b d e f -> cons a b c d e f)) as bs ds es fs
"foldr6/4" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (es :: Infinite elt5) (fs :: Infinite elt6) (g :: forall b. (elt4 -> b -> b) -> b).
  foldr6 cons as bs cs (build g) es fs =
    g (foldr6_left (\d a b c e f -> cons a b c d e f)) as bs cs es fs
"foldr6/5" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (fs :: Infinite elt6) (g :: forall b. (elt5 -> b -> b) -> b).
  foldr6 cons as bs cs ds (build g) fs =
    g (foldr6_left (\e a b c d f -> cons a b c d e f)) as bs cs ds fs
"foldr6/6" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (es :: Infinite elt5) (g :: forall b. (elt6 -> b -> b) -> b).
  foldr6 cons as bs cs ds es (build g) =
    g (foldr6_left (\f a b c d e -> cons a b c d e f)) as bs cs ds es
  #-}

-- | Zip seven infinite lists.
zip7 :: Infinite a -> Infinite b -> Infinite c -> Infinite d -> Infinite e -> Infinite f -> Infinite g -> Infinite (a, b, c, d, e, f, g)
zip7 = zipWith7 (,,,,,,)
{-# INLINE zip7 #-}

-- | Zip seven infinite lists with a given function.
zipWith7 :: (a -> b -> c -> d -> e -> f -> g -> h) -> Infinite a -> Infinite b -> Infinite c -> Infinite d -> Infinite e -> Infinite f -> Infinite g -> Infinite h
zipWith7 fun = go
  where
    go (a :< as) (b :< bs) (c :< cs) (d :< ds) (e :< es) (f :< fs) (g :< gs) = fun a b c d e f g :< go as bs cs ds es fs gs

zipWith7FB :: (elt -> lst -> lst') -> (a -> b -> c -> d -> e -> f -> g -> elt) -> a -> b -> c -> d -> e -> f -> g -> lst -> lst'
zipWith7FB = (.) . (.) . (.) . (.) . (.) . (.) . (.)

{-# NOINLINE [1] zipWith7 #-}

{-# INLINE [0] zipWith7FB #-}

{-# RULES
"zipWith7" [~1] forall f xs ys zs ts us vs ws.
  zipWith7 f xs ys zs ts us vs ws =
    build (\cons -> foldr7 (zipWith7FB cons f) xs ys zs ts us vs ws)
"zipWith7List" [1] forall f.
  foldr7 (zipWith7FB (:<) f) =
    zipWith7 f
  #-}

foldr7 :: (elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> elt7 -> lst -> lst) -> Infinite elt1 -> Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> Infinite elt5 -> Infinite elt6 -> Infinite elt7 -> lst
foldr7 cons = go
  where
    go (a :< as) (b :< bs) (c :< cs) (d :< ds) (e :< es) (f :< fs) (g :< gs) = cons a b c d e f g (go as bs cs ds es fs gs)
{-# INLINE [0] foldr7 #-}

foldr7_left :: (elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> elt7 -> lst -> lst') -> elt1 -> (Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> Infinite elt5 -> Infinite elt6 -> Infinite elt7 -> lst) -> Infinite elt2 -> Infinite elt3 -> Infinite elt4 -> Infinite elt5 -> Infinite elt6 -> Infinite elt7 -> lst'
foldr7_left cons a r (b :< bs) (c :< cs) (d :< ds) (e :< es) (f :< fs) (g :< gs) = cons a b c d e f g (r bs cs ds es fs gs)

{-# RULES
"foldr7/1" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> elt7 -> lst -> lst) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (es :: Infinite elt5) (fs :: Infinite elt6) (gs :: Infinite elt7) (g :: forall b. (elt1 -> b -> b) -> b).
  foldr7 cons (build g) bs cs ds es fs gs =
    g (foldr7_left cons) bs cs ds es fs gs
"foldr7/2" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> elt7 -> lst -> lst) (as :: Infinite elt1) (cs :: Infinite elt3) (ds :: Infinite elt4) (es :: Infinite elt5) (fs :: Infinite elt6) (gs :: Infinite elt7) (g :: forall b. (elt2 -> b -> b) -> b).
  foldr7 cons as (build g) cs ds es fs gs =
    g (foldr7_left (flip cons)) as cs ds es fs gs
"foldr7/3" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> elt7 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (ds :: Infinite elt4) (es :: Infinite elt5) (fs :: Infinite elt6) (gs :: Infinite elt7) (g :: forall b. (elt3 -> b -> b) -> b).
  foldr7 cons as bs (build g) ds es fs gs =
    g (foldr7_left (\c a b d e f g' -> cons a b c d e f g')) as bs ds es fs gs
"foldr7/4" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> elt7 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (es :: Infinite elt5) (fs :: Infinite elt6) (gs :: Infinite elt7) (g :: forall b. (elt4 -> b -> b) -> b).
  foldr7 cons as bs cs (build g) es fs gs =
    g (foldr7_left (\d a b c e f g' -> cons a b c d e f g')) as bs cs es fs gs
"foldr7/5" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> elt7 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (fs :: Infinite elt6) (gs :: Infinite elt7) (g :: forall b. (elt5 -> b -> b) -> b).
  foldr7 cons as bs cs ds (build g) fs gs =
    g (foldr7_left (\e a b c d f g' -> cons a b c d e f g')) as bs cs ds fs gs
"foldr7/6" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> elt7 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (es :: Infinite elt5) (gs :: Infinite elt7) (g :: forall b. (elt6 -> b -> b) -> b).
  foldr7 cons as bs cs ds es (build g) gs =
    g (foldr7_left (\f a b c d e g' -> cons a b c d e f g')) as bs cs ds es gs
"foldr7/7" forall (cons :: elt1 -> elt2 -> elt3 -> elt4 -> elt5 -> elt6 -> elt7 -> lst -> lst) (as :: Infinite elt1) (bs :: Infinite elt2) (cs :: Infinite elt3) (ds :: Infinite elt4) (es :: Infinite elt5) (fs :: Infinite elt6) (g :: forall b. (elt7 -> b -> b) -> b).
  foldr7 cons as bs cs ds es fs (build g) =
    g (foldr7_left (\g' a b c d e f -> cons a b c d e f g')) as bs cs ds es fs
  #-}
