module Data.Zip where

import qualified Data.NonEmpty.Class as C

import qualified Data.Traversable as Trav
import Data.Traversable (Traversable, )
import Control.Applicative (Applicative, pure, (<*>), )
import Control.DeepSeq (NFData, rnf, )


{- |
Wrap a container such that its Applicative instance is based on zip.
-}
newtype T f a = Cons {forall (f :: * -> *) a. T f a -> f a
decons :: f a}

instance Functor f => Functor (T f) where
   fmap :: forall a b. (a -> b) -> T f a -> T f b
fmap a -> b
f (Cons f a
xs) = forall (f :: * -> *) a. f a -> T f a
Cons forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f f a
xs

instance (C.Zip f, C.Repeat f) => Applicative (T f) where
   pure :: forall a. a -> T f a
pure a
a = forall (f :: * -> *) a. f a -> T f a
Cons forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Repeat f => a -> f a
C.repeat a
a
   Cons f (a -> b)
f <*> :: forall a b. T f (a -> b) -> T f a -> T f b
<*> Cons f a
x = forall (f :: * -> *) a. f a -> T f a
Cons forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b c.
Zip f =>
(a -> b -> c) -> f a -> f b -> f c
C.zipWith forall a b. (a -> b) -> a -> b
($) f (a -> b)
f f a
x


instance (C.NFData f, NFData a) => NFData (T f a) where
   rnf :: T f a -> ()
rnf = forall (f :: * -> *) a. (NFData f, NFData a) => f a -> ()
C.rnf

instance (C.NFData f) => C.NFData (T f) where
   rnf :: forall a. NFData a => T f a -> ()
rnf = forall (f :: * -> *) a. (NFData f, NFData a) => f a -> ()
C.rnf forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a. T f a -> f a
decons


{- |
Always returns a rectangular list
by clipping all dimensions to the shortest slice.
Be aware that @transpose [] == repeat []@.
-}
transposeClip ::
   (Traversable f, C.Zip g, C.Repeat g) =>
   f (g a) -> g (f a)
transposeClip :: forall (f :: * -> *) (g :: * -> *) a.
(Traversable f, Zip g, Repeat g) =>
f (g a) -> g (f a)
transposeClip =
   forall (f :: * -> *) a. T f a -> f a
decons forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
Trav.sequenceA forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (f :: * -> *) a. f a -> T f a
Cons