linear-generics-0.1.0.0: tests/Generics/Deriving/Traversable.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE Safe #-}
-- | A generic implementation of a 'Traversable'-like class.
-- See "Generics.Deriving.TraversableConf" for a more efficient,
-- but also more complicated, version.
module Generics.Deriving.Traversable (
-- * Generic Traversable class
GTraversable(..)
-- * Default method
, gtraversedefault
-- * Internal Traversable class
, GTraversable'(..)
) where
import Control.Applicative (Const, WrappedMonad(..), ZipList)
import qualified Data.Monoid as Monoid (First, Last, Product, Sum)
import Data.Monoid (Dual)
import Generics.Linear
import Generics.Deriving.Foldable
import Generics.Deriving.Functor
import Data.Complex (Complex)
import Data.Ord (Down)
import Data.Proxy (Proxy)
import Data.Functor.Identity (Identity)
import qualified Data.Functor.Product as Functor (Product)
import qualified Data.Functor.Sum as Functor (Sum)
import Data.List.NonEmpty (NonEmpty)
import qualified Data.Semigroup as Semigroup (First, Last)
import Data.Semigroup (Arg, Max, Min, WrappedMonoid)
--------------------------------------------------------------------------------
-- Generic traverse
--------------------------------------------------------------------------------
class GTraversable' t where
gtraverse' :: Applicative f => (a -> f b) -> t a -> f (t b)
instance GTraversable' V1 where
gtraverse' _ x = pure $ case x of
instance GTraversable' U1 where
gtraverse' _ U1 = pure U1
instance GTraversable' Par1 where
gtraverse' f (Par1 a) = Par1 <$> f a
instance GTraversable' (K1 i c) where
gtraverse' _ (K1 a) = pure (K1 a)
instance GTraversable' f => GTraversable' (M1 i c f) where
gtraverse' f (M1 a) = M1 <$> gtraverse' f a
instance GTraversable' f => GTraversable' (MP1 m f) where
gtraverse' f (MP1 a) = (\x -> MP1 x) <$> gtraverse' f a
instance (GTraversable' f, GTraversable' g) => GTraversable' (f :+: g) where
gtraverse' f (L1 a) = L1 <$> gtraverse' f a
gtraverse' f (R1 a) = R1 <$> gtraverse' f a
instance (GTraversable' f, GTraversable' g) => GTraversable' (f :*: g) where
gtraverse' f (a :*: b) = (:*:) <$> gtraverse' f a <*> gtraverse' f b
instance (GTraversable' f, GTraversable g) => GTraversable' (f :.: g) where
gtraverse' f (Comp1 x) = Comp1 <$> gtraverse' (gtraverse f) x
instance GTraversable' UAddr where
gtraverse' _ (UAddr a) = pure (UAddr a)
instance GTraversable' UChar where
gtraverse' _ (UChar c) = pure (UChar c)
instance GTraversable' UDouble where
gtraverse' _ (UDouble d) = pure (UDouble d)
instance GTraversable' UFloat where
gtraverse' _ (UFloat f) = pure (UFloat f)
instance GTraversable' UInt where
gtraverse' _ (UInt i) = pure (UInt i)
instance GTraversable' UWord where
gtraverse' _ (UWord w) = pure (UWord w)
class (GFunctor t, GFoldable t) => GTraversable t where
gtraverse :: Applicative f => (a -> f b) -> t a -> f (t b)
default gtraverse :: (Generic1 t, GTraversable' (Rep1 t), Applicative f)
=> (a -> f b) -> t a -> f (t b)
gtraverse = gtraversedefault
gsequenceA :: Applicative f => t (f a) -> f (t a)
gsequenceA = gtraverse id
gmapM :: Monad m => (a -> m b) -> t a -> m (t b)
gmapM f = unwrapMonad . gtraverse (WrapMonad . f)
gsequence :: Monad m => t (m a) -> m (t a)
gsequence = gmapM id
gtraversedefault :: (Generic1 t, GTraversable' (Rep1 t), Applicative f)
=> (a -> f b) -> t a -> f (t b)
gtraversedefault f x = to1 <$> gtraverse' f (from1 x)
-- Base types instances
instance GTraversable ((,) a)
instance GTraversable []
instance GTraversable (Arg a)
instance GTraversable Complex
instance GTraversable (Const m)
instance GTraversable Down
instance GTraversable Dual
instance GTraversable (Either a)
instance GTraversable Monoid.First
instance GTraversable (Semigroup.First)
instance GTraversable Identity
instance GTraversable Monoid.Last
instance GTraversable Semigroup.Last
instance GTraversable Max
instance GTraversable Maybe
instance GTraversable Min
instance GTraversable NonEmpty
instance GTraversable Monoid.Product
instance (GTraversable f, GTraversable g) => GTraversable (Functor.Product f g)
instance GTraversable Proxy
instance GTraversable Monoid.Sum
instance (GTraversable f, GTraversable g) => GTraversable (Functor.Sum f g)
instance GTraversable WrappedMonoid
instance GTraversable ZipList