module Data.Append where

import qualified Data.NonEmpty.Class as C
import Control.Applicative (liftA2)
import Control.DeepSeq (NFData, rnf, )
import Data.Traversable (Traversable, traverse)
import Data.Foldable (Foldable, foldMap)
import Data.Monoid (mappend)

import Prelude hiding (fst, snd)


data T f g a =
   Cons {
      T f g a -> f a
fst :: f a,
      T f g a -> g a
snd :: g a
   }

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

instance (Foldable f, Foldable g) => Foldable (T f g) where
   foldMap :: (a -> m) -> T f g a -> m
foldMap a -> m
f (Cons f a
xs g a
ys) = m -> m -> m
forall a. Monoid a => a -> a -> a
mappend ((a -> m) -> f a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f f a
xs) ((a -> m) -> g a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f g a
ys)

instance (Traversable f, Traversable g) => Traversable (T f g) where
   traverse :: (a -> f b) -> T f g a -> f (T f g b)
traverse a -> f b
f (Cons f a
xs g a
ys) = (f b -> g b -> T f g b) -> f (f b) -> f (g b) -> f (T f g b)
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 f b -> g b -> T f g b
forall (f :: * -> *) (g :: * -> *) a. f a -> g a -> T f g a
Cons ((a -> f b) -> f a -> f (f b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f f a
xs) ((a -> f b) -> g a -> f (g b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f g a
ys)


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

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