module SimpleH.Traversable(
  module SimpleH.Applicative, module SimpleH.Foldable,

  Traversable(..),Contravariant(..),

  traverse,foreach,transpose,flip
  ) where

import SimpleH.Classes
import SimpleH.Core hiding (flip,(&))
import SimpleH.Applicative
import SimpleH.Foldable
import SimpleH.Lens
import Data.Tree

class Foldable t => Traversable t where
  sequence :: Applicative f => t (f a) -> f (t a)
instance Traversable ((,) c) where
  sequence ~(c,m) = (,) c<$>m
instance Traversable (Either a) where
  sequence = pure . Left <|> map Right
instance Traversable [] where
  sequence (x:xs) = (:)<$>x<*>sequence xs
  sequence [] = pure []
deriving instance Traversable Interleave
deriving instance Traversable OrdList
deriving instance Traversable ZipList
instance Traversable Tree where
  sequence (Node a subs) = Node<$>a<*>sequence (map sequence subs)
deriving instance Traversable ZipTree
instance (Traversable f,Traversable g) => Traversable (Compose f g) where
  sequence = getCompose >>> map sequence >>> sequence >>> map Compose

class Functor t => Contravariant t where
  collect :: Functor f => f (t a) -> t (f a)
instance Contravariant Id where collect f = Id (map getId f)
instance Contravariant ((->) a) where collect f = \a -> map ($a) f

traverse f t = sequence (map f t)
foreach = flip traverse
transpose = sequence
flip = collect

instance Compound a b [a] [b] where
  _each = traverse