{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Barbies.Internal.TraversableT
( TraversableT(..)
, ttraverse_
, tsequence
, tsequence'
, tfoldMap
, CanDeriveTraversableT
, ttraverseDefault
)
where
import Barbies.Generics.Traversable(GTraversable(..))
import Barbies.Internal.FunctorT(FunctorT (..))
import Barbies.Internal.Writer(execWr, tell)
import Control.Applicative.Backwards(Backwards (..))
import Control.Applicative.Lift(Lift(..))
import Control.Monad.Trans.Except(ExceptT(..))
import Control.Monad.Trans.Identity(IdentityT(..))
import Control.Monad.Trans.Maybe(MaybeT(..))
import Control.Monad.Trans.Writer.Lazy as Lazy (WriterT(..))
import Control.Monad.Trans.Writer.Strict as Strict (WriterT(..))
import Data.Functor (void)
import Data.Functor.Compose (Compose (..))
import Data.Functor.Const (Const (..))
import Data.Functor.Identity (Identity (..))
import Data.Functor.Product (Product (..))
import Data.Functor.Reverse (Reverse (..))
import Data.Functor.Sum (Sum (..))
import Data.Kind (Type)
import Data.Generics.GenericN
import Data.Proxy (Proxy (..))
class FunctorT t => TraversableT (t :: (k -> Type) -> k' -> Type) where
ttraverse
:: Applicative e
=> (forall a . f a -> e (g a))
-> (forall x . t f x -> e (t g x))
default ttraverse
:: ( Applicative e, CanDeriveTraversableT t f g x)
=> (forall a . f a -> e (g a)) -> t f x -> e (t g x)
ttraverse = ttraverseDefault
ttraverse_
:: (TraversableT t, Applicative e)
=> (forall a. f a -> e c)
-> t f x -> e ()
ttraverse_ f
= void . ttraverse (fmap (const $ Const ()) . f)
tsequence
:: (Applicative e, TraversableT t)
=> t (Compose e f) x
-> e (t f x)
tsequence
= ttraverse getCompose
tsequence'
:: (Applicative e, TraversableT t)
=> t e x
-> e (t Identity x)
tsequence'
= ttraverse (fmap Identity)
tfoldMap
:: ( TraversableT t, Monoid m)
=> (forall a. f a -> m)
-> t f x
-> m
tfoldMap f
= execWr . ttraverse_ (tell . f)
type CanDeriveTraversableT t f g x
= ( GenericP 1 (t f x)
, GenericP 1 (t g x)
, GTraversable 1 f g (RepP 1 (t f x)) (RepP 1 (t g x))
)
ttraverseDefault
:: forall t f g e x
. (Applicative e, CanDeriveTraversableT t f g x)
=> (forall a . f a -> e (g a))
-> t f x -> e (t g x)
ttraverseDefault h
= fmap (toP (Proxy @1)) . gtraverse (Proxy @1) h . fromP (Proxy @1)
{-# INLINE ttraverseDefault #-}
type P = Param
instance
( TraversableT t
) => GTraversable 1 f g (Rec (t (P 1 f) x) (t f x))
(Rec (t (P 1 g) x) (t g x))
where
gtraverse _ h
= fmap (Rec . K1) . ttraverse h . unK1 . unRec
{-# INLINE gtraverse #-}
instance
( Traversable h
, TraversableT t
) => GTraversable 1 f g (Rec (h (t (P 1 f) x)) (h (t f x)))
(Rec (h (t (P 1 g) x)) (h (t g x)))
where
gtraverse _ h
= fmap (Rec . K1) . traverse (ttraverse h) . unK1 . unRec
{-# INLINE gtraverse #-}
instance
( Traversable h
, Traversable m
, TraversableT t
) => GTraversable 1 f g (Rec (m (h (t (P 1 f) x))) (m (h (t f x))))
(Rec (m (h (t (P 1 g) x))) (m (h (t g x))))
where
gtraverse _ h
= fmap (Rec . K1) . traverse (traverse (ttraverse h)) . unK1 . unRec
{-# INLINE gtraverse #-}
instance Traversable f => TraversableT (Compose f) where
ttraverse h (Compose fga)
= Compose <$> traverse h fga
{-# INLINE ttraverse #-}
instance TraversableT (Product f) where
ttraverse h (Pair fa ga) = Pair fa <$> h ga
{-# INLINE ttraverse #-}
instance TraversableT (Sum f) where
ttraverse h = \case
InL fa -> pure $ InL fa
InR ga -> InR <$> h ga
{-# INLINE ttraverse #-}
instance TraversableT Backwards where
ttraverse h (Backwards fa)
= Backwards <$> h fa
{-# INLINE ttraverse #-}
instance TraversableT Lift where
ttraverse h = \case
Pure a -> pure $ Pure a
Other fa -> Other <$> h fa
{-# INLINE ttraverse #-}
instance TraversableT Reverse where
ttraverse h (Reverse fa) = Reverse <$> h fa
{-# INLINE ttraverse #-}
instance TraversableT (ExceptT e) where
ttraverse h (ExceptT mea)
= ExceptT <$> h mea
{-# INLINE ttraverse #-}
instance TraversableT IdentityT where
ttraverse h (IdentityT ma)
= IdentityT <$> h ma
{-# INLINE ttraverse #-}
instance TraversableT MaybeT where
ttraverse h (MaybeT mma)
= MaybeT <$> h mma
{-# INLINE ttraverse #-}
instance TraversableT (Lazy.WriterT w) where
ttraverse h (Lazy.WriterT maw)
= Lazy.WriterT <$> h maw
{-# INLINE ttraverse #-}
instance TraversableT (Strict.WriterT w) where
ttraverse h (Strict.WriterT maw)
= Strict.WriterT <$> h maw
{-# INLINE ttraverse #-}