{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Barbies.Internal.TraversableB
( TraversableB(..)
, btraverse_
, bsequence
, bsequence'
, bfoldMap
, CanDeriveTraversableB
, gbtraverseDefault
)
where
import Barbies.Generics.Traversable(GTraversable(..))
import Barbies.Internal.FunctorB(FunctorB (..))
import Barbies.Internal.Writer(execWr, tell)
import Data.Functor (void)
import Data.Functor.Compose (Compose (..))
import Data.Functor.Const (Const (..))
import Data.Functor.Constant (Constant (..))
import Data.Functor.Identity (Identity (..))
import Data.Functor.Product (Product (..))
import Data.Functor.Sum (Sum (..))
import Data.Kind (Type)
import Data.Generics.GenericN
import Data.Proxy (Proxy (..))
class FunctorB b => TraversableB (b :: (k -> Type) -> Type) where
btraverse :: Applicative e => (forall a . f a -> e (g a)) -> b f -> e (b g)
default btraverse
:: ( Applicative e, CanDeriveTraversableB b f g)
=> (forall a . f a -> e (g a))
-> b f
-> e (b g)
btraverse = gbtraverseDefault
btraverse_
:: (TraversableB b, Applicative e)
=> (forall a. f a -> e c)
-> b f
-> e ()
btraverse_ f
= void . btraverse (fmap (const $ Const ()) . f)
bsequence :: (Applicative e, TraversableB b) => b (Compose e f) -> e (b f)
bsequence
= btraverse getCompose
bsequence' :: (Applicative e, TraversableB b) => b e -> e (b Identity)
bsequence'
= btraverse (fmap Identity)
bfoldMap :: (TraversableB b, Monoid m) => (forall a. f a -> m) -> b f -> m
bfoldMap f
= execWr . btraverse_ (tell . f)
type CanDeriveTraversableB b f g
= ( GenericP 0 (b f)
, GenericP 0 (b g)
, GTraversable 0 f g (RepP 0 (b f)) (RepP 0 (b g))
)
gbtraverseDefault
:: forall b f g e
. (Applicative e, CanDeriveTraversableB b f g)
=> (forall a . f a -> e (g a))
-> b f -> e (b g)
gbtraverseDefault h
= fmap (toP (Proxy @0)) . gtraverse (Proxy @0) h . fromP (Proxy @0)
{-# INLINE gbtraverseDefault #-}
type P = Param
instance
( TraversableB b
) => GTraversable 0 f g (Rec (b (P 0 f)) (b f))
(Rec (b (P 0 g)) (b g))
where
gtraverse _ h
= fmap (Rec . K1) . btraverse h . unK1 . unRec
{-# INLINE gtraverse #-}
instance
( Traversable h
, TraversableB b
) => GTraversable 0 f g (Rec (h (b (P 0 f))) (h (b f)))
(Rec (h (b (P 0 g))) (h (b g)))
where
gtraverse _ h
= fmap (Rec . K1) . traverse (btraverse h) . unK1 . unRec
{-# INLINE gtraverse #-}
instance
( Traversable h
, Traversable m
, TraversableB b
) => GTraversable 0 f g (Rec (m (h (b (P 0 f)))) (m (h (b f))))
(Rec (m (h (b (P 0 g)))) (m (h (b g))))
where
gtraverse _ h
= fmap (Rec . K1) . traverse (traverse (btraverse h)) . unK1 . unRec
{-# INLINE gtraverse #-}
instance TraversableB Proxy where
btraverse _ _ = pure Proxy
{-# INLINE btraverse #-}
instance (TraversableB a, TraversableB b) => TraversableB (Product a b) where
btraverse f (Pair x y) = Pair <$> btraverse f x <*> btraverse f y
{-# INLINE btraverse #-}
instance (TraversableB a, TraversableB b) => TraversableB (Sum a b) where
btraverse f (InL x) = InL <$> btraverse f x
btraverse f (InR x) = InR <$> btraverse f x
{-# INLINE btraverse #-}
instance TraversableB (Const a) where
btraverse _ (Const x) = pure (Const x)
{-# INLINE btraverse #-}
instance (Traversable f, TraversableB b) => TraversableB (f `Compose` b) where
btraverse h (Compose x)
= Compose <$> traverse (btraverse h) x
{-# INLINE btraverse #-}
instance TraversableB (Constant a) where
btraverse _ (Constant x) = pure (Constant x)
{-# INLINE btraverse #-}