{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeOperators #-}
#if __GLASGOW_HASKELL__ >=706
{-# LANGUAGE PolyKinds #-}
#endif
#if __GLASGOW_HASKELL__ >=702
{-# LANGUAGE Trustworthy #-}
#endif
module Data.Foldable1 (
Foldable1(..),
foldr1, foldr1',
foldl1, foldl1',
intercalate1,
foldrM1,
foldlM1,
foldrMapM1,
foldlMapM1,
maximumBy,
minimumBy,
) where
import Data.Foldable (Foldable, foldlM, foldr)
import Data.List (foldl, foldl')
import Data.List.NonEmpty (NonEmpty (..))
import Data.Semigroup
(Dual (..), First (..), Last (..), Max (..), Min (..), Product (..),
Semigroup (..), Sum (..))
import Prelude
(Maybe (..), Monad (..), Ord, Ordering (..), id, seq, ($!), ($), (.),
(=<<), flip, const)
import qualified Data.List.NonEmpty as NE
#if MIN_VERSION_base(4,4,0)
import Data.Complex (Complex (..))
import GHC.Generics
(M1 (..), Par1 (..), Rec1 (..), V1, (:*:) (..), (:+:) (..), (:.:) (..))
import Prelude (error)
#endif
#if MIN_VERSION_base(4,6,0)
import Data.Ord (Down (..))
#endif
#if MIN_VERSION_base(4,8,0)
import qualified Data.Monoid as Mon
#endif
#if !MIN_VERSION_base(4,12,0)
import Data.Orphans ()
#endif
#ifdef MIN_VERSION_tagged
import Data.Tagged (Tagged (..))
#endif
import Control.Applicative.Backwards (Backwards (..))
import Control.Applicative.Lift (Lift (..))
import Control.Monad.Trans.Identity (IdentityT (..))
import Data.Functor.Compose (Compose (..))
import Data.Functor.Identity (Identity (..))
import Data.Functor.Reverse (Reverse (..))
import Data.Tree (Tree (..))
import qualified Data.Functor.Product as Functor
import qualified Data.Functor.Sum as Functor
#if __GLASGOW_HASKELL__ <708
import Unsafe.Coerce (unsafeCoerce)
#else
import Data.Coerce (Coercible, coerce)
#endif
class Foldable t => Foldable1 t where
#if __GLASGOW_HASKELL__ >= 708
{-# MINIMAL foldMap1 | foldrMap1 #-}
#endif
fold1 :: Semigroup m => t m -> m
fold1 = foldMap1 id
foldMap1 :: Semigroup m => (a -> m) -> t a -> m
foldMap1 f = foldrMap1 f (\a m -> f a <> m)
foldMap1' :: Semigroup m => (a -> m) -> t a -> m
foldMap1' f = foldlMap1' f (\m a -> m <> f a)
toNonEmpty :: t a -> NonEmpty a
toNonEmpty = runNonEmptyDList . foldMap1 singleton
maximum :: Ord a => t a -> a
maximum = getMax #. foldMap1' Max
minimum :: Ord a => t a -> a
minimum = getMin #. foldMap1' Min
head :: t a -> a
head = getFirst #. foldMap1 First
last :: t a -> a
last = getLast #. foldMap1 Last
foldrMap1 :: (a -> b) -> (a -> b -> b) -> t a -> b
foldrMap1 f g xs =
appFromMaybe (foldMap1 (FromMaybe #. h) xs) Nothing
where
h a Nothing = f a
h a (Just b) = g a b
foldlMap1' :: (a -> b) -> (b -> a -> b) -> t a -> b
foldlMap1' f g xs =
foldrMap1 f' g' xs SNothing
where
f' a SNothing = f a
f' a (SJust b) = g b a
g' a x SNothing = x $! SJust (f a)
g' a x (SJust b) = x $! SJust (g b a)
foldlMap1 :: (a -> b) -> (b -> a -> b) -> t a -> b
foldlMap1 f g xs =
appFromMaybe (getDual (foldMap1 ((Dual . FromMaybe) #. h) xs)) Nothing
where
h a Nothing = f a
h a (Just b) = g b a
foldrMap1' :: (a -> b) -> (a -> b -> b) -> t a -> b
foldrMap1' f g xs =
foldlMap1 f' g' xs SNothing
where
f' a SNothing = f a
f' a (SJust b) = g a b
g' bb a SNothing = bb $! SJust (f a)
g' bb a (SJust b) = bb $! SJust (g a b)
foldr1 :: Foldable1 t => (a -> a -> a) -> t a -> a
foldr1 = foldrMap1 id
{-# INLINE foldr1 #-}
foldr1' :: Foldable1 t => (a -> a -> a) -> t a -> a
foldr1' = foldrMap1' id
{-# INLINE foldr1' #-}
foldl1 :: Foldable1 t => (a -> a -> a) -> t a -> a
foldl1 = foldlMap1 id
{-# INLINE foldl1 #-}
foldl1' :: Foldable1 t => (a -> a -> a) -> t a -> a
foldl1' = foldlMap1' id
{-# INLINE foldl1' #-}
intercalate1 :: (Foldable1 t, Semigroup m) => m -> t m -> m
intercalate1 = flip intercalateMap1 id
intercalateMap1 :: (Foldable1 t, Semigroup m) => m -> (a -> m) -> t a -> m
intercalateMap1 j f = flip joinee j . foldMap1 (JoinWith . const . f)
foldrM1 :: (Foldable1 t, Monad m) => (a -> a -> m a) -> t a -> m a
foldrM1 = foldrMapM1 return
foldrMapM1 :: (Foldable1 t, Monad m) => (a -> m b) -> (a -> b -> m b) -> t a -> m b
foldrMapM1 g f = go . toNonEmpty
where
go (e:|es) =
case es of
[] -> g e
x:xs -> f e =<< go (x:|xs)
foldlM1 :: (Foldable1 t, Monad m) => (a -> a -> m a) -> t a -> m a
foldlM1 = foldlMapM1 return
foldlMapM1 :: (Foldable1 t, Monad m) => (a -> m b) -> (b -> a -> m b) -> t a -> m b
foldlMapM1 g f t = g x >>= \y -> foldlM f y xs
where x:|xs = toNonEmpty t
maximumBy :: Foldable1 t => (a -> a -> Ordering) -> t a -> a
maximumBy cmp = foldl1' max'
where max' x y = case cmp x y of
GT -> x
_ -> y
minimumBy :: Foldable1 t => (a -> a -> Ordering) -> t a -> a
minimumBy cmp = foldl1' min'
where min' x y = case cmp x y of
GT -> y
_ -> x
newtype NonEmptyDList a = NEDL { unNEDL :: [a] -> NonEmpty a }
instance Semigroup (NonEmptyDList a) where
xs <> ys = NEDL (unNEDL xs . NE.toList . unNEDL ys)
{-# INLINE (<>) #-}
singleton :: a -> NonEmptyDList a
singleton = NEDL #. (:|)
runNonEmptyDList :: NonEmptyDList a -> NonEmpty a
runNonEmptyDList = ($ []) . unNEDL
{-# INLINE runNonEmptyDList #-}
newtype FromMaybe b = FromMaybe { appFromMaybe :: Maybe b -> b }
instance Semigroup (FromMaybe b) where
FromMaybe f <> FromMaybe g = FromMaybe (f . Just . g)
data SMaybe a = SNothing | SJust !a
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
instance Foldable1 NonEmpty where
foldMap1 f (x :| xs) = go (f x) xs where
go y [] = y
go y (z : zs) = y <> go (f z) zs
foldMap1' f (x :| xs) = foldl' (\m y -> m <> f y) (f x) xs
toNonEmpty = id
foldrMap1 g f (x :| xs) = go x xs where
go y [] = g y
go y (z : zs) = f y (go z zs)
foldlMap1 g f (x :| xs) = foldl f (g x) xs
foldlMap1' g f (x :| xs) = let gx = g x in gx `seq` foldl' f gx xs
head = NE.head
last = NE.last
#if MIN_VERSION_base(4,6,0)
instance Foldable1 Down where
foldMap1 = coerce
#endif
#if MIN_VERSION_base(4,4,0)
instance Foldable1 Complex where
foldMap1 f (x :+ y) = f x <> f y
toNonEmpty (x :+ y) = x :| y : []
#endif
instance Foldable1 ((,) a) where
foldMap1 f (_, y) = f y
toNonEmpty (_, x) = x :| []
minimum (_, x) = x
maximum (_, x) = x
head (_, x) = x
last (_, x) = x
instance Foldable1 Dual where
foldMap1 = coerce
instance Foldable1 Sum where
foldMap1 = coerce
instance Foldable1 Product where
foldMap1 = coerce
instance Foldable1 Min where
foldMap1 = coerce
instance Foldable1 Max where
foldMap1 = coerce
instance Foldable1 First where
foldMap1 = coerce
instance Foldable1 Last where
foldMap1 = coerce
#if MIN_VERSION_base(4,8,0)
deriving instance (Foldable1 f) => Foldable1 (Mon.Alt f)
#endif
#if MIN_VERSION_base(4,12,0)
deriving instance (Foldable1 f) => Foldable1 (Mon.Ap f)
#endif
#if MIN_VERSION_base(4,4,0)
instance Foldable1 V1 where
foldMap1 _ x = x `seq` error "foldMap1 @V1"
instance Foldable1 Par1 where
foldMap1 = coerce
deriving instance Foldable1 f => Foldable1 (Rec1 f)
deriving instance Foldable1 f => Foldable1 (M1 i c f)
instance (Foldable1 f, Foldable1 g) => Foldable1 (f :+: g) where
foldMap1 f (L1 x) = foldMap1 f x
foldMap1 f (R1 y) = foldMap1 f y
instance (Foldable1 f, Foldable1 g) => Foldable1 (f :*: g) where
foldMap1 f (x :*: y) = foldMap1 f x <> foldMap1 f y
instance (Foldable1 f, Foldable1 g) => Foldable1 (f :.: g) where
foldMap1 f = foldMap1 (foldMap1 f) . unComp1
#endif
instance Foldable1 Identity where
foldMap1 = coerce
foldrMap1 g _ = coerce g
foldrMap1' g _ = coerce g
foldlMap1 g _ = coerce g
foldlMap1' g _ = coerce g
toNonEmpty (Identity x) = x :| []
last = coerce
head = coerce
minimum = coerce
maximum = coerce
instance (Foldable1 f, Foldable1 g) => Foldable1 (Functor.Product f g) where
foldMap1 f (Functor.Pair x y) = foldMap1 f x <> foldMap1 f y
foldrMap1 g f (Functor.Pair x y) = foldr f (foldrMap1 g f y) x
head (Functor.Pair x _) = head x
last (Functor.Pair _ y) = last y
instance (Foldable1 f, Foldable1 g) => Foldable1 (Functor.Sum f g) where
foldMap1 f (Functor.InL x) = foldMap1 f x
foldMap1 f (Functor.InR y) = foldMap1 f y
foldrMap1 g f (Functor.InL x) = foldrMap1 g f x
foldrMap1 g f (Functor.InR y) = foldrMap1 g f y
toNonEmpty (Functor.InL x) = toNonEmpty x
toNonEmpty (Functor.InR y) = toNonEmpty y
head (Functor.InL x) = head x
head (Functor.InR y) = head y
last (Functor.InL x) = last x
last (Functor.InR y) = last y
minimum (Functor.InL x) = minimum x
minimum (Functor.InR y) = minimum y
maximum (Functor.InL x) = maximum x
maximum (Functor.InR y) = maximum y
instance (Foldable1 f, Foldable1 g) => Foldable1 (Compose f g) where
foldMap1 f = foldMap1 (foldMap1 f) . getCompose
foldrMap1 f g = foldrMap1 (foldrMap1 f g) (\xs x -> foldr g x xs) . getCompose
head = head . head . getCompose
last = last . last . getCompose
instance Foldable1 Tree where
foldMap1 f (Node x []) = f x
foldMap1 f (Node x (y : ys)) = f x <> foldMap1 (foldMap1 f) (y :| ys)
foldMap1' f = go where
go (Node x ys) =
foldl' (\m zs -> let gozs = go zs in gozs `seq` m <> gozs) (f x) ys
foldlMap1 f g (Node x xs) = goForest (f x) xs where
goForest = foldl' go
go y (Node z zs) = goForest (g y z) zs
foldlMap1' f g (Node x xs) = goForest (f x) xs where
goForest !y = foldl' go y
go !y (Node z zs) = goForest (g y z) zs
head (Node x _) = x
instance Foldable1 f => Foldable1 (Reverse f) where
foldMap1 f = getDual . foldMap1 (Dual . f) . getReverse
foldrMap1 f g (Reverse xs) = foldlMap1 f (flip g) xs
foldlMap1 f g (Reverse xs) = foldrMap1 f (flip g) xs
foldrMap1' f g (Reverse xs) = foldlMap1' f (flip g) xs
foldlMap1' f g (Reverse xs) = foldrMap1' f (flip g) xs
head = last . getReverse
last = head . getReverse
deriving instance Foldable1 f => Foldable1 (IdentityT f)
instance Foldable1 f => Foldable1 (Backwards f) where
foldMap1 f = foldMap1 f . forwards
instance Foldable1 f => Foldable1 (Lift f) where
foldMap1 f (Pure x) = f x
foldMap1 f (Other y) = foldMap1 f y
#ifdef MIN_VERSION_tagged
instance Foldable1 (Tagged b) where
foldMap1 = coerce
foldrMap1 g _ = coerce g
foldrMap1' g _ = coerce g
foldlMap1 g _ = coerce g
foldlMap1' g _ = coerce g
toNonEmpty x = coerce x :| []
last = coerce
head = coerce
minimum = coerce
maximum = coerce
#endif
#if __GLASGOW_HASKELL__ <708
coerce :: a -> b
coerce = unsafeCoerce
(#.) :: (b -> c) -> (a -> b) -> a -> c
(#.) _f = coerce
#else
(#.) :: Coercible b c => (b -> c) -> (a -> b) -> a -> c
(#.) _f = coerce
#endif