#if __GLASGOW_HASKELL__ >= 707
#endif
module Control.Comonad.Trans.Coiter
  (
  
  
  
  
  
  
  
  
  
  
  
    CoiterT(..)
  
  , Coiter, coiter, runCoiter
  
  , unfold
  
  , ComonadCofree(..)
  
  
  ) where
import Control.Arrow hiding (second)
import Control.Comonad
import Control.Comonad.Cofree.Class
import Control.Comonad.Env.Class
import Control.Comonad.Hoist.Class
import Control.Comonad.Store.Class
import Control.Comonad.Traced.Class
import Control.Comonad.Trans.Class
import Control.Category
import Data.Bifunctor
import Data.Bifoldable
import Data.Bitraversable
import Data.Data
import Data.Foldable
import Data.Function (on)
import Data.Functor.Identity
import Data.Traversable
import Prelude hiding (id,(.))
import Prelude.Extras
newtype CoiterT w a = CoiterT { runCoiterT :: w (a, CoiterT w a) }
#if __GLASGOW_HASKELL__ >= 707
  deriving Typeable
#endif
instance (Functor w, Eq1 w) => Eq1 (CoiterT w) where
  (==#) = on (==#) (fmap (fmap Lift1) . runCoiterT)
instance (Functor w, Ord1 w) => Ord1 (CoiterT w) where
  compare1 = on compare1 (fmap (fmap Lift1) . runCoiterT)
instance (Functor w, Show1 w) => Show1 (CoiterT w) where
  showsPrec1 d (CoiterT as) = showParen (d > 10) $
    showString "CoiterT " . showsPrec1 11 (fmap (fmap Lift1) as)
instance (Functor w, Read1 w) => Read1 (CoiterT w) where
  readsPrec1 d =  readParen (d > 10) $ \r ->
    [ (CoiterT (fmap (fmap lower1) m),t) | ("CoiterT",s) <- lex r, (m,t) <- readsPrec1 11 s]
type Coiter = CoiterT Identity
coiter :: a -> Coiter a -> Coiter a
coiter a as = CoiterT $ Identity (a,as)
runCoiter :: Coiter a -> (a, Coiter a)
runCoiter = runIdentity . runCoiterT
instance Functor w => Functor (CoiterT w) where
  fmap f = CoiterT . fmap (bimap f (fmap f)) . runCoiterT
instance Comonad w => Comonad (CoiterT w) where
  extract = fst . extract . runCoiterT
  
  extend f = CoiterT . extend (\w -> (f (CoiterT w), extend f $ snd $ extract w)) . runCoiterT
instance Foldable w => Foldable (CoiterT w) where
  foldMap f = foldMap (bifoldMap f (foldMap f)) . runCoiterT
instance Traversable w => Traversable (CoiterT w) where
  traverse f = fmap CoiterT . traverse (bitraverse f (traverse f)) . runCoiterT
instance ComonadTrans CoiterT where
  lower = fmap fst . runCoiterT
instance Comonad w => ComonadCofree Identity (CoiterT w) where
  unwrap = Identity . snd . extract . runCoiterT
  
  
instance ComonadEnv e w => ComonadEnv e (CoiterT w) where
  ask = ask . lower
  
  
instance ComonadHoist CoiterT where
  cohoist g = CoiterT . fmap (second (cohoist g)) . g . runCoiterT
instance ComonadTraced m w => ComonadTraced m (CoiterT w) where
  trace m = trace m . lower
  
instance ComonadStore s w => ComonadStore s (CoiterT w) where
  pos = pos . lower
  peek s = peek s . lower
  peeks f = peeks f . lower
  seek = seek
  seeks = seeks
  experiment f = experiment f . lower
  
  
  
  
  
  
instance Show (w (a, CoiterT w a)) => Show (CoiterT w a) where
  showsPrec d w = showParen (d > 10) $
    showString "CoiterT " . showsPrec 11 w
instance Read (w (a, CoiterT w a)) => Read (CoiterT w a) where
  readsPrec d = readParen (d > 10) $ \r ->
     [(CoiterT w, t) | ("CoiterT", s) <- lex r, (w, t) <- readsPrec 11 s]
instance Eq (w (a, CoiterT w a)) => Eq (CoiterT w a) where
  CoiterT a == CoiterT b = a == b
  
instance Ord (w (a, CoiterT w a)) => Ord (CoiterT w a) where
  compare (CoiterT a) (CoiterT b) = compare a b
  
unfold :: Comonad w => (w a -> a) -> w a -> CoiterT w a
unfold psi = CoiterT . extend (extract &&& unfold psi . extend psi)
#if __GLASGOW_HASKELL__ < 707
instance Typeable1 w => Typeable1 (CoiterT w) where
  typeOf1 t = mkTyConApp coiterTTyCon [typeOf1 (w t)] where
    w :: CoiterT w a -> w a
    w = undefined
coiterTTyCon :: TyCon
#if __GLASGOW_HASKELL__ < 704
coiterTTyCon = mkTyCon "Control.Comonad.Trans.Coiter.CoiterT"
#else
coiterTTyCon = mkTyCon3 "free" "Control.Comonad.Trans.Coiter" "CoiterT"
#endif
#else
#define Typeable1 Typeable
#endif
instance
  ( Typeable1 w, Typeable a
  , Data (w (a, CoiterT w a))
  , Data a
  ) => Data (CoiterT w a) where
    gfoldl f z (CoiterT w) = z CoiterT `f` w
    toConstr _ = coiterTConstr
    gunfold k z c = case constrIndex c of
        1 -> k (z CoiterT)
        _ -> error "gunfold"
    dataTypeOf _ = coiterTDataType
    dataCast1 f = gcast1 f
coiterTConstr :: Constr
coiterTConstr = mkConstr coiterTDataType "CoiterT" [] Prefix
coiterTDataType :: DataType
coiterTDataType = mkDataType "Control.Comonad.Trans.Coiter.CoiterT" [coiterTConstr]