module Data.Semigroup.Foldable
( Foldable1(..)
, intercalate1
, intercalateMap1
, traverse1_
, for1_
, sequenceA1_
, foldMapDefault1
, asum1
, foldrM1
, foldlM1
) where
import Data.Foldable
import Data.Functor.Alt (Alt(..))
import Data.Functor.Apply
import Data.List.NonEmpty (NonEmpty(..))
import Data.Traversable.Instances ()
import Data.Semigroup hiding (Product, Sum)
import Data.Semigroup.Foldable.Class
import Prelude hiding (foldr)
newtype JoinWith a = JoinWith {joinee :: (a -> a)}
instance Semigroup a => Semigroup (JoinWith a) where
JoinWith a <> JoinWith b = JoinWith $ \j -> a j <> j <> b j
intercalate1 :: (Foldable1 t, Semigroup m) => m -> t m -> m
intercalate1 = flip intercalateMap1 id
{-# INLINE intercalate1 #-}
intercalateMap1 :: (Foldable1 t, Semigroup m) => m -> (a -> m) -> t a -> m
intercalateMap1 j f = flip joinee j . foldMap1 (JoinWith . const . f)
{-# INLINE intercalateMap1 #-}
newtype Act f a = Act { getAct :: f a }
instance Apply f => Semigroup (Act f a) where
Act a <> Act b = Act (a .> b)
instance Functor f => Functor (Act f) where
fmap f (Act a) = Act (f <$> a)
b <$ Act a = Act (b <$ a)
traverse1_ :: (Foldable1 t, Apply f) => (a -> f b) -> t a -> f ()
traverse1_ f t = () <$ getAct (foldMap1 (Act . f) t)
{-# INLINE traverse1_ #-}
for1_ :: (Foldable1 t, Apply f) => t a -> (a -> f b) -> f ()
for1_ = flip traverse1_
{-# INLINE for1_ #-}
sequenceA1_ :: (Foldable1 t, Apply f) => t (f a) -> f ()
sequenceA1_ t = () <$ getAct (foldMap1 Act t)
{-# INLINE sequenceA1_ #-}
foldMapDefault1 :: (Foldable1 t, Monoid m) => (a -> m) -> t a -> m
foldMapDefault1 f = unwrapMonoid . foldMap (WrapMonoid . f)
{-# INLINE foldMapDefault1 #-}
newtype Alt_ f a = Alt_ { getAlt_ :: f a }
instance Alt f => Semigroup (Alt_ f a) where
Alt_ a <> Alt_ b = Alt_ (a <!> b)
asum1 :: (Foldable1 t, Alt m) => t (m a) -> m a
asum1 = getAlt_ . foldMap1 Alt_
{-# INLINE asum1 #-}
foldrM1 :: (Foldable1 t, Monad m) => (a -> a -> m a) -> t a -> m a
foldrM1 f = go . toNonEmpty
where
g = (=<<) . f
go (e:|es) =
case es of
[] -> return e
x:xs -> e `g` (go (x:|xs))
foldlM1 :: (Foldable1 t, Monad m) => (a -> a -> m a) -> t a -> m a
foldlM1 f t = foldlM f x xs
where
x:|xs = toNonEmpty t