constrained-0.1: src/Data/Traversable/Constrained.hs
----------------------------------------------------------------------------
-- |
-- Module : Data.Traversable.Constrained
-- Copyright : (c) Sergey Vinokurov 2019
-- License : BSD-2 (see LICENSE)
-- Maintainer : sergey@debian
----------------------------------------------------------------------------
{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Traversable.Constrained
( CTraversable(..)
, cfor
, module Data.Constrained
) where
import Control.Applicative (ZipList(..))
import Data.Functor.Compose (Compose(..))
import Data.Functor.Const (Const(..))
import Data.Functor.Identity (Identity(..))
import Data.Functor.Product as Product
import Data.Functor.Sum (Sum(..))
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.Monoid as Monoid
import qualified Data.Semigroup as Semigroup
import Data.Constrained (Constrained(..))
import Data.Foldable.Constrained
import Data.Functor.Constrained
-- | Like 'Traversable' but allows elements to have constraints on them.
-- Laws are the same:
--
-- > ctraverse pure == pure
-- > ctraverse (f <=< g) == ctraverse f <=< ctraverse g
--
-- NB There's no aplicative version because Vectors from the
-- http://hackage.haskell.org/package/vector package only support
-- monadic traversals. Since they're one of the main motivation for
-- this package, 'Applicative' version of traversals will not exist.
class (CFunctor f, CFoldable f) => CTraversable f where
ctraverse
:: (Constraints f a, Constraints f b, Monad m)
=> (a -> m b) -> f a -> m (f b)
{-# INLINE csequence #-}
csequence
:: (Constraints f a, Constraints f (m a), Monad m)
=> f (m a) -> m (f a)
csequence = ctraverse id
{-# INLINE ctraverse #-}
default ctraverse
:: (Constraints f a, Constraints f b, Monad m, Traversable f)
=> (a -> m b) -> f a -> m (f b)
ctraverse = traverse
instance CTraversable [] where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable NonEmpty where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable Identity where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable ((,) a) where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable Maybe where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable (Either a) where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable (Const a) where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable ZipList where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable Semigroup.Min where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable Semigroup.Max where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable Semigroup.First where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable Semigroup.Last where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable Semigroup.Dual where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable Semigroup.Sum where
{-# INLINE csequence #-}
csequence = sequenceA
instance CTraversable Semigroup.Product where
{-# INLINE csequence #-}
csequence = sequenceA
#if MIN_VERSION_base(4,12,0)
instance CTraversable f => CTraversable (Monoid.Ap f) where
{-# INLINE ctraverse #-}
{-# INLINE csequence #-}
ctraverse f = fmap Monoid.Ap . ctraverse f . Monoid.getAp
csequence = fmap Monoid.Ap . csequence . Monoid.getAp
#endif
instance CTraversable f => CTraversable (Monoid.Alt f) where
{-# INLINE ctraverse #-}
{-# INLINE csequence #-}
ctraverse f = fmap Monoid.Alt . ctraverse f . Monoid.getAlt
csequence = fmap Monoid.Alt . csequence . Monoid.getAlt
instance (CTraversable f, CTraversable g) => CTraversable (Compose f g) where
{-# INLINABLE ctraverse #-}
ctraverse f = fmap Compose . ctraverse (ctraverse f) . getCompose
instance (CTraversable f, CTraversable g) => CTraversable (Product f g) where
{-# INLINABLE ctraverse #-}
ctraverse f (Pair x y) = Pair <$> ctraverse f x <*> ctraverse f y
instance (CTraversable f, CTraversable g) => CTraversable (Sum f g) where
{-# INLINABLE ctraverse #-}
ctraverse f (InL x) = InL <$> ctraverse f x
ctraverse f (InR y) = InR <$> ctraverse f y
{-# INLINE cfor #-}
-- | 'ctraverse' with araguments flipped.
cfor
:: (CTraversable f, Constraints f a, Constraints f b, Monad m)
=> f a -> (a -> m b) -> m (f b)
cfor = flip ctraverse