{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Singletons.Prelude.Foldable (
PFoldable(..), SFoldable(..),
FoldrM, sFoldrM,
FoldlM, sFoldlM,
Traverse_, sTraverse_,
For_, sFor_,
SequenceA_, sSequenceA_,
Asum, sAsum,
MapM_, sMapM_,
ForM_, sForM_,
Sequence_, sSequence_,
Msum, sMsum,
Concat, sConcat,
ConcatMap, sConcatMap,
And, sAnd,
Or, sOr,
Any, sAny,
All, sAll,
MaximumBy, sMaximumBy,
MinimumBy, sMinimumBy,
NotElem, sNotElem,
Find, sFind,
FoldSym0, FoldSym1,
FoldMapSym0, FoldMapSym1, FoldMapSym2,
FoldrSym0, FoldrSym1, FoldrSym2, FoldrSym3,
Foldr'Sym0, Foldr'Sym1, Foldr'Sym2, Foldr'Sym3,
FoldlSym0, FoldlSym1, FoldlSym2, FoldlSym3,
Foldl'Sym0, Foldl'Sym1, Foldl'Sym2, Foldl'Sym3,
Foldr1Sym0, Foldr1Sym1, Foldr1Sym2,
Foldl1Sym0, Foldl1Sym1, Foldl1Sym2,
ToListSym0, ToListSym1,
NullSym0, NullSym1,
LengthSym0, LengthSym1,
ElemSym0, ElemSym1, ElemSym2,
MaximumSym0, MaximumSym1,
MinimumSym0, MinimumSym1,
SumSym0, SumSym1,
ProductSym0, ProductSym1,
FoldrMSym0, FoldrMSym1, FoldrMSym2, FoldrMSym3,
FoldlMSym0, FoldlMSym1, FoldlMSym2, FoldlMSym3,
Traverse_Sym0, Traverse_Sym1, Traverse_Sym2,
For_Sym0, For_Sym1, For_Sym2,
SequenceA_Sym0, SequenceA_Sym1,
AsumSym0, AsumSym1,
MapM_Sym0, MapM_Sym1, MapM_Sym2,
ForM_Sym0, ForM_Sym1, ForM_Sym2,
Sequence_Sym0, Sequence_Sym1,
MsumSym0, MsumSym1,
ConcatSym0, ConcatSym1,
ConcatMapSym0, ConcatMapSym1, ConcatMapSym2,
AndSym0, AndSym1,
OrSym0, OrSym1,
AnySym0, AnySym1, AnySym2,
AllSym0, AllSym1, AllSym2,
MaximumBySym0, MaximumBySym1, MaximumBySym2,
MinimumBySym0, MinimumBySym1, MinimumBySym2,
NotElemSym0, NotElemSym1, NotElemSym2,
FindSym0, FindSym1, FindSym2
) where
import Control.Applicative
import Control.Monad
import Data.Kind
import Data.List.NonEmpty (NonEmpty(..))
import Data.Monoid hiding (All(..), Any(..), Endo(..), Product(..), Sum(..))
import qualified Data.Monoid as Monoid (All(..), Any(..), Product(..), Sum(..))
import Data.Singletons.Internal
import Data.Singletons.Prelude.Base
hiding (Foldr, FoldrSym0, FoldrSym1, FoldrSym2, FoldrSym3, sFoldr)
import Data.Singletons.Prelude.Bool
import Data.Singletons.Prelude.Either
import Data.Singletons.Prelude.Eq
import Data.Singletons.Prelude.Instances (Sing(..), type (:@#@$))
import Data.Singletons.Prelude.List.Internal.Disambiguation
import Data.Singletons.Prelude.Maybe
import Data.Singletons.Prelude.Monad.Internal
import Data.Singletons.Prelude.Monoid
hiding ( AllSym0, AllSym1
, AnySym0, AnySym1
, ProductSym0, ProductSym1
, SumSym0, SumSym1 )
import Data.Singletons.Prelude.Num
import Data.Singletons.Prelude.Ord
hiding ( Max, MaxSym0, MaxSym1, MaxSym2, sMax
, Min, MinSym0, MinSym1, MinSym2, sMin )
import Data.Singletons.Prelude.Semigroup.Internal
hiding ( AllSym0(..), AllSym1, SAll
, AnySym0(..), AnySym1, SAny
, FirstSym0, FirstSym1, SFirst
, LastSym0, LastSym1, SLast
, ProductSym0(..), ProductSym1, SProduct
, SumSym0(..), SumSym1, SSum )
import Data.Singletons.Promote
import Data.Singletons.Single
import Data.Singletons.TypeLits.Internal
newtype Endo a = Endo (a ~> a)
data instance Sing :: forall a. Endo a -> Type where
SEndo :: Sing x -> Sing ('Endo x)
data EndoSym0 :: forall a. (a ~> a) ~> Endo a
type instance Apply EndoSym0 x = 'Endo x
$(singletonsOnly [d|
instance Semigroup (Endo a) where
Endo x <> Endo y = Endo (x . y)
instance Monoid (Endo a) where
mempty = Endo id
|])
newtype MaxInternal a = MaxInternal (Maybe a)
data instance Sing :: forall a. MaxInternal a -> Type where
SMaxInternal :: Sing x -> Sing ('MaxInternal x)
$(genDefunSymbols [''MaxInternal])
newtype MinInternal a = MinInternal (Maybe a)
data instance Sing :: forall a. MinInternal a -> Type where
SMinInternal :: Sing x -> Sing ('MinInternal x)
$(genDefunSymbols [''MinInternal])
$(singletonsOnly [d|
instance Ord a => Semigroup (MaxInternal a) where
m <> MaxInternal Nothing = m
MaxInternal Nothing <> n = n
(MaxInternal m@(Just x)) <> (MaxInternal n@(Just y))
= if x >= y then MaxInternal m else MaxInternal n
instance Ord a => Monoid (MaxInternal a) where
mempty = MaxInternal Nothing
instance Ord a => Semigroup (MinInternal a) where
m <> MinInternal Nothing = m
MinInternal Nothing <> n = n
(MinInternal m@(Just x)) <> (MinInternal n@(Just y))
= if x <= y then MinInternal m else MinInternal n
instance Ord a => Monoid (MinInternal a) where
mempty = MinInternal Nothing
|])
$(singletonsOnly [d|
class Foldable (t :: Type -> Type) where
fold :: Monoid m => t m -> m
fold = foldMap id
foldMap :: Monoid m => (a -> m) -> t a -> m
foldMap f = foldr (mappend . f) mempty
foldr :: (a -> b -> b) -> b -> t a -> b
foldr f z t = case foldMap (Endo . f) t of
Endo g -> g z
foldr' :: (a -> b -> b) -> b -> t a -> b
foldr' f z0 xs = foldl f' id xs z0
where f' k x z = k $! f x z
foldl :: (b -> a -> b) -> b -> t a -> b
foldl f z t = case foldMap (Dual . Endo . flip f) t of
Dual (Endo g) -> g z
foldl' :: (b -> a -> b) -> b -> t a -> b
foldl' f z0 xs = foldr f' id xs z0
where f' x k z = k $! f z x
foldr1 :: (a -> a -> a) -> t a -> a
foldr1 f xs = fromMaybe (errorWithoutStackTrace "foldr1: empty structure")
(foldr mf Nothing xs)
where
mf x m = Just (case m of
Nothing -> x
Just y -> f x y)
foldl1 :: (a -> a -> a) -> t a -> a
foldl1 f xs = fromMaybe (errorWithoutStackTrace "foldl1: empty structure")
(foldl mf Nothing xs)
where
mf m y = Just (case m of
Nothing -> y
Just x -> f x y)
toList :: t a -> [a]
toList = foldr (:) []
null :: t a -> Bool
null = foldr (\_ _ -> False) True
length :: t a -> Nat
length = foldl' (\c _ -> c+1) 0
elem :: Eq a => a -> t a -> Bool
elem = any . (==)
maximum :: forall a . Ord a => t a -> a
maximum x =
case foldMap (MaxInternal . Just) x of
MaxInternal y -> fromMaybe (errorWithoutStackTrace "maximum: empty structure") y
minimum :: forall a . Ord a => t a -> a
minimum x =
case foldMap (MinInternal . Just) x of
MinInternal y -> fromMaybe (errorWithoutStackTrace "minimum: empty structure") y
sum :: Num a => t a -> a
sum x = case foldMap sum_ x of
Monoid.Sum y -> y
product :: Num a => t a -> a
product x = case foldMap product_ x of
Monoid.Product y -> y
instance Foldable Maybe where
foldMap = maybe_ mempty
foldr _ z Nothing = z
foldr f z (Just x) = f x z
foldl _ z Nothing = z
foldl f z (Just x) = f z x
instance Foldable [] where
elem = listelem
foldl = listfoldl
foldl' = listfoldl'
foldl1 = listfoldl1
foldr = listfoldr
foldr1 = listfoldr1
length = listlength
maximum = listmaximum
minimum = listminimum
null = listnull
product = listproduct
sum = listsum
toList = id
instance Foldable NonEmpty where
foldr f z (a :| as) = f a (listfoldr f z as)
foldl f z (a :| as) = listfoldl f (f z a) as
foldl1 f (a :| as) = listfoldl f a as
foldr1 f (p :| ps) = foldr go id ps p
where
go x r prev = f prev (r x)
foldMap f (a :| as) = f a `mappend` foldMap f as
fold (m :| ms) = m `mappend` fold ms
toList (a :| as) = a : as
instance Foldable (Either a) where
foldMap _ (Left _) = mempty
foldMap f (Right y) = f y
foldr _ z (Left _) = z
foldr f z (Right y) = f y z
length (Left _) = 0
length (Right _) = 1
null = isLeft
instance Foldable Dual where
foldMap f (Dual x) = f x
elem x (Dual y) = x == y
foldl f z (Dual x) = f z x
foldl' f z (Dual x) = f z x
foldl1 _ (Dual x) = x
foldr f z (Dual x) = f x z
foldr' = foldr
foldr1 _ (Dual x) = x
length _ = 1
maximum (Dual x) = x
minimum (Dual x) = x
null _ = False
product (Dual x) = x
sum (Dual x) = x
toList (Dual x) = [x]
instance Foldable Monoid.Sum where
foldMap f (Monoid.Sum x) = f x
elem x (Monoid.Sum y) = x == y
foldl f z (Monoid.Sum x) = f z x
foldl' f z (Monoid.Sum x) = f z x
foldl1 _ (Monoid.Sum x) = x
foldr f z (Monoid.Sum x) = f x z
foldr' = foldr
foldr1 _ (Monoid.Sum x) = x
length _ = 1
maximum (Monoid.Sum x) = x
minimum (Monoid.Sum x) = x
null _ = False
product (Monoid.Sum x) = x
sum (Monoid.Sum x) = x
toList (Monoid.Sum x) = [x]
instance Foldable Monoid.Product where
foldMap f (Monoid.Product x) = f x
elem x (Monoid.Product y) = x == y
foldl f z (Monoid.Product x) = f z x
foldl' f z (Monoid.Product x) = f z x
foldl1 _ (Monoid.Product x) = x
foldr f z (Monoid.Product x) = f x z
foldr' = foldr
foldr1 _ (Monoid.Product x) = x
length _ = 1
maximum (Monoid.Product x) = x
minimum (Monoid.Product x) = x
null _ = False
product (Monoid.Product x) = x
sum (Monoid.Product x) = x
toList (Monoid.Product x) = [x]
foldrM :: (Foldable t, Monad m) => (a -> b -> m b) -> b -> t a -> m b
foldrM f z0 xs = foldl f' return xs z0
where f' k x z = f x z >>= k
foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldr f' return xs z0
where f' x k z = f z x >>= k
traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()
traverse_ f = foldr ((*>) . f) (pure ())
for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f ()
for_ = flip traverse_
mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
mapM_ f= foldr ((>>) . f) (return ())
forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()
forM_ = flip mapM_
sequenceA_ :: (Foldable t, Applicative f) => t (f a) -> f ()
sequenceA_ = foldr (*>) (pure ())
sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
sequence_ = foldr (>>) (return ())
asum :: (Foldable t, Alternative f) => t (f a) -> f a
asum = foldr (<|>) empty
msum :: (Foldable t, MonadPlus m) => t (m a) -> m a
msum = asum
concat :: Foldable t => t [a] -> [a]
concat xs = foldr (\x y -> foldr (:) y x) [] xs
concatMap :: Foldable t => (a -> [b]) -> t a -> [b]
concatMap f xs = foldr (\x b -> foldr (:) b (f x)) [] xs
and :: Foldable t => t Bool -> Bool
and x = case foldMap all_ x of
Monoid.All y -> y
or :: Foldable t => t Bool -> Bool
or x = case foldMap any_ x of
Monoid.Any y -> y
any :: Foldable t => (a -> Bool) -> t a -> Bool
any p x = case foldMap (any_ . p) x of
Monoid.Any y -> y
all :: Foldable t => (a -> Bool) -> t a -> Bool
all p x = case foldMap (all_ . p) x of
Monoid.All y -> y
maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a
maximumBy cmp = foldl1 max'
where max' x y = case cmp x y of
GT -> x
LT -> y
EQ -> y
minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a
minimumBy cmp = foldl1 min'
where min' x y = case cmp x y of
GT -> y
LT -> x
EQ -> x
notElem :: (Foldable t, Eq a) => a -> t a -> Bool
notElem x = not . elem x
find :: Foldable t => (a -> Bool) -> t a -> Maybe a
find p y = case foldMap (\ x -> First (if p x then Just x else Nothing)) y of
First z -> z
|])
$(singletonsOnly [d|
deriving instance Foldable ((,) a)
deriving instance Foldable First
deriving instance Foldable Last
|])