module Control.ConstraintClasses.Extras
       ( CZippable (..) ) where

import Control.ConstraintClasses

class CFunctor f => CZippable f where
  czip :: (CFun f a, CFun f b, CFun f (a,b))
       => f a -> f b -> f (a,b)

  czipWith :: ( CFun f a
              , CFun f b
              , CFun f (a,b)
              , CFun f c)
          => (a -> b -> c) -> f a -> f b -> f c
  czipWith f x y = cmap (uncurry f) (czip x y)

  czipWith3 :: ( CFun f a
               , CFun f b
               , CFun f c
               , CFun f (a,b)
               , CFun f ((a,b),c)
               , CFun f d )
            => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
  czipWith3 f x y z = cmap ((uncurry . uncurry) f)
                           (czip (czip x y) z)

  czipWith4 :: (CFun f a, CFun f b, CFun f c, CFun f d, CFun f e)
            => (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e