module Control.Foldl (
Fold(..)
, FoldM(..)
, fold
, foldM
, scan
#if MIN_VERSION_base(4,8,0)
, prescan
, postscan
#else
#endif
, Control.Foldl.mconcat
, Control.Foldl.foldMap
, head
, last
, lastDef
, lastN
, null
, length
, and
, or
, all
, any
, sum
, product
, mean
, variance
, std
, maximum
, maximumBy
, minimum
, minimumBy
, elem
, notElem
, find
, index
, lookup
, elemIndex
, findIndex
, random
, randomN
, Control.Foldl.mapM_
, sink
, genericLength
, genericIndex
, list
, revList
, nub
, eqNub
, set
, hashSet
, map
, hashMap
, vector
, vectorM
, purely
, purely_
, impurely
, impurely_
, generalize
, simplify
, hoists
, duplicateM
, _Fold1
, premap
, premapM
, prefilter
, prefilterM
, Handler
, handles
, foldOver
, EndoM(..)
, HandlerM
, handlesM
, foldOverM
, folded
, filtered
, module Control.Monad.Primitive
, module Data.Foldable
, module Data.Vector.Generic
) where
import Control.Applicative
import Control.Foldl.Internal (Maybe'(..), lazy, Either'(..), hush)
import Control.Monad ((<=<))
import Control.Monad.Primitive (PrimMonad, RealWorld)
import Control.Comonad
import Data.Foldable (Foldable)
import Data.Functor.Identity (Identity, runIdentity)
import Data.Functor.Contravariant (Contravariant(..))
import Data.Monoid hiding ((<>))
import Data.Semigroup (Semigroup(..))
import Data.Profunctor
import Data.Sequence ((|>))
import Data.Vector.Generic (Vector, Mutable)
import Data.Vector.Generic.Mutable (MVector)
import Data.Hashable (Hashable)
import System.Random.MWC (GenIO, createSystemRandom, uniformR)
import Prelude hiding
( head
, last
, null
, length
, and
, or
, all
, any
, sum
, product
, maximum
, minimum
, elem
, notElem
, lookup
, map
)
import qualified Data.Foldable as F
import qualified Data.List as List
import qualified Data.Sequence as Seq
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map
import qualified Data.HashMap.Strict as HashMap
import qualified Data.HashSet as HashSet
import qualified Data.Vector.Generic as V
import qualified Data.Vector.Generic.Mutable as M
import qualified VectorBuilder.Builder
import qualified VectorBuilder.Vector
data Fold a b
= forall x. Fold (x -> a -> x) x (x -> b)
data Pair a b = Pair !a !b
instance Functor (Fold a) where
fmap f (Fold step begin done) = Fold step begin (f . done)
instance Profunctor Fold where
lmap = premap
rmap = fmap
instance Choice Fold where
right' (Fold step begin done) = Fold (liftA2 step) (Right begin) (fmap done)
instance Comonad (Fold a) where
extract (Fold _ begin done) = done begin
duplicate (Fold step begin done) = Fold step begin (\x -> Fold step x done)
instance Applicative (Fold a) where
pure b = Fold (\() _ -> ()) () (\() -> b)
(Fold stepL beginL doneL) <*> (Fold stepR beginR doneR) =
let step (Pair xL xR) a = Pair (stepL xL a) (stepR xR a)
begin = Pair beginL beginR
done (Pair xL xR) = doneL xL (doneR xR)
in Fold step begin done
instance Monoid b => Semigroup (Fold a b) where
(<>) = liftA2 mappend
instance Monoid b => Monoid (Fold a b) where
mempty = pure mempty
mappend = (<>)
instance Num b => Num (Fold a b) where
fromInteger = pure . fromInteger
negate = fmap negate
abs = fmap abs
signum = fmap signum
(+) = liftA2 (+)
(*) = liftA2 (*)
() = liftA2 ()
instance Fractional b => Fractional (Fold a b) where
fromRational = pure . fromRational
recip = fmap recip
(/) = liftA2 (/)
instance Floating b => Floating (Fold a b) where
pi = pure pi
exp = fmap exp
sqrt = fmap sqrt
log = fmap log
sin = fmap sin
tan = fmap tan
cos = fmap cos
asin = fmap asin
atan = fmap atan
acos = fmap acos
sinh = fmap sinh
tanh = fmap tanh
cosh = fmap cosh
asinh = fmap asinh
atanh = fmap atanh
acosh = fmap acosh
(**) = liftA2 (**)
logBase = liftA2 logBase
data FoldM m a b =
forall x . FoldM (x -> a -> m x) (m x) (x -> m b)
instance Monad m => Functor (FoldM m a) where
fmap f (FoldM step start done) = FoldM step start done'
where
done' x = do
b <- done x
return $! f b
instance Monad m => Applicative (FoldM m a) where
pure b = FoldM (\() _ -> return ()) (return ()) (\() -> return b)
(FoldM stepL beginL doneL) <*> (FoldM stepR beginR doneR) =
let step (Pair xL xR) a = do
xL' <- stepL xL a
xR' <- stepR xR a
return $! Pair xL' xR'
begin = do
xL <- beginL
xR <- beginR
return $! Pair xL xR
done (Pair xL xR) = do
f <- doneL xL
x <- doneR xR
return $! f x
in FoldM step begin done
instance Monad m => Profunctor (FoldM m) where
rmap = fmap
lmap = premapM
instance (Monoid b, Monad m) => Semigroup (FoldM m a b) where
(<>) = liftA2 mappend
instance (Monoid b, Monad m) => Monoid (FoldM m a b) where
mempty = pure mempty
mappend = liftA2 mappend
instance (Monad m, Num b) => Num (FoldM m a b) where
fromInteger = pure . fromInteger
negate = fmap negate
abs = fmap abs
signum = fmap signum
(+) = liftA2 (+)
(*) = liftA2 (*)
() = liftA2 ()
instance (Monad m, Fractional b) => Fractional (FoldM m a b) where
fromRational = pure . fromRational
recip = fmap recip
(/) = liftA2 (/)
instance (Monad m, Floating b) => Floating (FoldM m a b) where
pi = pure pi
exp = fmap exp
sqrt = fmap sqrt
log = fmap log
sin = fmap sin
tan = fmap tan
cos = fmap cos
asin = fmap asin
atan = fmap atan
acos = fmap acos
sinh = fmap sinh
tanh = fmap tanh
cosh = fmap cosh
asinh = fmap asinh
atanh = fmap atanh
acosh = fmap acosh
(**) = liftA2 (**)
logBase = liftA2 logBase
fold :: Foldable f => Fold a b -> f a -> b
fold (Fold step begin done) as = F.foldr cons done as begin
where
cons a k x = k $! step x a
foldM :: (Foldable f, Monad m) => FoldM m a b -> f a -> m b
foldM (FoldM step begin done) as0 = do
x0 <- begin
F.foldr step' done as0 $! x0
where
step' a k x = do
x' <- step x a
k $! x'
scan :: Fold a b -> [a] -> [b]
scan (Fold step begin done) as = foldr cons nil as begin
where
nil x = done x:[]
cons a k x = done x:(k $! step x a)
#if MIN_VERSION_base(4,8,0)
prescan :: Traversable t => Fold a b -> t a -> t b
prescan (Fold step begin done) as = bs
where
step' x a = (x', b)
where
x' = step x a
b = done x
(_, bs) = List.mapAccumL step' begin as
postscan :: Traversable t => Fold a b -> t a -> t b
postscan (Fold step begin done) as = bs
where
step' x a = (x', b)
where
x' = step x a
b = done x'
(_, bs) = List.mapAccumL step' begin as
#else
#endif
mconcat :: Monoid a => Fold a a
mconcat = Fold mappend mempty id
foldMap :: Monoid w => (a -> w) -> (w -> b) -> Fold a b
foldMap to = Fold (\x a -> mappend x (to a)) mempty
head :: Fold a (Maybe a)
head = _Fold1 const
last :: Fold a (Maybe a)
last = _Fold1 (flip const)
lastDef :: a -> Fold a a
lastDef a = Fold (\_ a' -> a') a id
lastN :: Int -> Fold a [a]
lastN n = Fold step begin done
where
step s a = s' |> a
where
s' =
if Seq.length s < n
then s
else Seq.drop 1 s
begin = Seq.empty
done = F.toList
null :: Fold a Bool
null = Fold (\_ _ -> False) True id
length :: Fold a Int
length = genericLength
and :: Fold Bool Bool
and = Fold (&&) True id
or :: Fold Bool Bool
or = Fold (||) False id
all :: (a -> Bool) -> Fold a Bool
all predicate = Fold (\x a -> x && predicate a) True id
any :: (a -> Bool) -> Fold a Bool
any predicate = Fold (\x a -> x || predicate a) False id
sum :: Num a => Fold a a
sum = Fold (+) 0 id
product :: Num a => Fold a a
product = Fold (*) 1 id
mean :: Fractional a => Fold a a
mean = Fold step begin done
where
begin = Pair 0 0
step (Pair x n) y = Pair ((x * n + y) / (n + 1)) (n + 1)
done (Pair x _) = x
variance :: Fractional a => Fold a a
variance = Fold step begin done
where
begin = Pair3 0 0 0
step (Pair3 n mean_ m2) x = Pair3 n' mean' m2'
where
n' = n + 1
mean' = (n * mean_ + x) / (n + 1)
delta = x mean_
m2' = m2 + delta * delta * n / (n + 1)
done (Pair3 n _ m2) = m2 / n
std :: Floating a => Fold a a
std = sqrt variance
maximum :: Ord a => Fold a (Maybe a)
maximum = _Fold1 max
maximumBy :: (a -> a -> Ordering) -> Fold a (Maybe a)
maximumBy cmp = _Fold1 max'
where
max' x y = case cmp x y of
GT -> x
_ -> y
minimum :: Ord a => Fold a (Maybe a)
minimum = _Fold1 min
minimumBy :: (a -> a -> Ordering) -> Fold a (Maybe a)
minimumBy cmp = _Fold1 min'
where
min' x y = case cmp x y of
GT -> y
_ -> x
elem :: Eq a => a -> Fold a Bool
elem a = any (a ==)
notElem :: Eq a => a -> Fold a Bool
notElem a = all (a /=)
find :: (a -> Bool) -> Fold a (Maybe a)
find predicate = Fold step Nothing' lazy
where
step x a = case x of
Nothing' -> if predicate a then Just' a else Nothing'
_ -> x
index :: Int -> Fold a (Maybe a)
index = genericIndex
elemIndex :: Eq a => a -> Fold a (Maybe Int)
elemIndex a = findIndex (a ==)
findIndex :: (a -> Bool) -> Fold a (Maybe Int)
findIndex predicate = Fold step (Left' 0) hush
where
step x a = case x of
Left' i ->
if predicate a
then Right' i
else Left' (i + 1)
_ -> x
lookup :: Eq a => a -> Fold (a,b) (Maybe b)
lookup a0 = Fold step Nothing' lazy
where
step x (a,b) = case x of
Nothing' -> if a == a0
then Just' b
else Nothing'
_ -> x
data Pair3 a b c = Pair3 !a !b !c
random :: FoldM IO a (Maybe a)
random = FoldM step begin done
where
begin = do
g <- createSystemRandom
return $! Pair3 g Nothing' (1 :: Int)
step (Pair3 g Nothing' _) a = return $! Pair3 g (Just' a) 2
step (Pair3 g (Just' a) m) b = do
n <- uniformR (1, m) g
let c = if n == 1 then b else a
return $! Pair3 g (Just' c) (m + 1)
done (Pair3 _ ma _) = return (lazy ma)
data VectorState = Incomplete !Int | Complete
data RandomNState v a = RandomNState
{ _size :: !VectorState
, _reservoir :: !(Mutable v RealWorld a)
, _position :: !Int
, _gen :: !GenIO
}
randomN :: Vector v a => Int -> FoldM IO a (Maybe (v a))
randomN n = FoldM step begin done
where
step
:: MVector (Mutable v) a
=> RandomNState v a -> a -> IO (RandomNState v a)
step (RandomNState (Incomplete m) mv i g) a = do
M.write mv m a
let m' = m + 1
let s = if n <= m' then Complete else Incomplete m'
return $! RandomNState s mv (i + 1) g
step (RandomNState Complete mv i g) a = do
r <- uniformR (0, i 1) g
if r < n
then M.unsafeWrite mv r a
else return ()
return (RandomNState Complete mv (i + 1) g)
begin = do
mv <- M.new n
gen <- createSystemRandom
let s = if n <= 0 then Complete else Incomplete 0
return (RandomNState s mv 1 gen)
done :: Vector v a => RandomNState v a -> IO (Maybe (v a))
done (RandomNState (Incomplete _) _ _ _) = return Nothing
done (RandomNState Complete mv _ _) = do
v <- V.freeze mv
return (Just v)
mapM_ :: Monad m => (a -> m ()) -> FoldM m a ()
mapM_ = sink
sink :: (Monoid w, Monad m) => (a -> m w) -> FoldM m a w
sink act = FoldM step begin done where
done = return
begin = return mempty
step m a = do
m' <- act a
return $! mappend m m'
genericLength :: Num b => Fold a b
genericLength = Fold (\n _ -> n + 1) 0 id
genericIndex :: Integral i => i -> Fold a (Maybe a)
genericIndex i = Fold step (Left' 0) done
where
step x a = case x of
Left' j -> if i == j then Right' a else Left' (j + 1)
_ -> x
done x = case x of
Left' _ -> Nothing
Right' a -> Just a
list :: Fold a [a]
list = Fold (\x a -> x . (a:)) id ($ [])
revList :: Fold a [a]
revList = Fold (\x a -> a:x) [] id
nub :: Ord a => Fold a [a]
nub = Fold step (Pair Set.empty id) fin
where
step (Pair s r) a = if Set.member a s
then Pair s r
else Pair (Set.insert a s) (r . (a :))
fin (Pair _ r) = r []
eqNub :: Eq a => Fold a [a]
eqNub = Fold step (Pair [] id) fin
where
step (Pair known r) a = if List.elem a known
then Pair known r
else Pair (a : known) (r . (a :))
fin (Pair _ r) = r []
set :: Ord a => Fold a (Set.Set a)
set = Fold (flip Set.insert) Set.empty id
hashSet :: (Eq a, Hashable a) => Fold a (HashSet.HashSet a)
hashSet = Fold (flip HashSet.insert) HashSet.empty id
map :: Ord a => Fold (a, b) (Map.Map a b)
map = Fold step begin done
where
begin = mempty
step m (k, v) = Map.insert k v m
done = id
hashMap :: (Eq a, Hashable a) => Fold (a, b) (HashMap.HashMap a b)
hashMap = Fold step begin done
where
begin = mempty
step m (k, v) = HashMap.insert k v m
done = id
vector :: Vector v a => Fold a (v a)
vector = Fold step begin done
where
begin = VectorBuilder.Builder.empty
step x a = x <> VectorBuilder.Builder.singleton a
done = VectorBuilder.Vector.build
maxChunkSize :: Int
maxChunkSize = 8 * 1024 * 1024
vectorM :: (PrimMonad m, Vector v a) => FoldM m a (v a)
vectorM = FoldM step begin done
where
begin = do
mv <- M.unsafeNew 10
return (Pair mv 0)
step (Pair mv idx) a = do
let len = M.length mv
mv' <- if idx >= len
then M.unsafeGrow mv (min len maxChunkSize)
else return mv
M.unsafeWrite mv' idx a
return (Pair mv' (idx + 1))
done (Pair mv idx) = do
v <- V.freeze mv
return (V.unsafeTake idx v)
purely :: (forall x . (x -> a -> x) -> x -> (x -> b) -> r) -> Fold a b -> r
purely f (Fold step begin done) = f step begin done
purely_ :: (forall x . (x -> a -> x) -> x -> x) -> Fold a b -> b
purely_ f (Fold step begin done) = done (f step begin)
impurely
:: (forall x . (x -> a -> m x) -> m x -> (x -> m b) -> r)
-> FoldM m a b
-> r
impurely f (FoldM step begin done) = f step begin done
impurely_
:: Monad m
=> (forall x . (x -> a -> m x) -> m x -> m x) -> FoldM m a b -> m b
impurely_ f (FoldM step begin done) = do
x <- f step begin
done x
generalize :: Monad m => Fold a b -> FoldM m a b
generalize (Fold step begin done) = FoldM step' begin' done'
where
step' x a = return (step x a)
begin' = return begin
done' x = return (done x)
simplify :: FoldM Identity a b -> Fold a b
simplify (FoldM step begin done) = Fold step' begin' done'
where
step' x a = runIdentity (step x a)
begin' = runIdentity begin
done' x = runIdentity (done x)
hoists :: (forall x . m x -> n x) -> FoldM m a b -> FoldM n a b
hoists phi (FoldM step begin done) = FoldM (\a b -> phi (step a b)) (phi begin) (phi . done)
duplicateM :: Applicative m => FoldM m a b -> FoldM m a (FoldM m a b)
duplicateM (FoldM step begin done) =
FoldM step begin (\x -> pure (FoldM step (pure x) done))
_Fold1 :: (a -> a -> a) -> Fold a (Maybe a)
_Fold1 step = Fold step_ Nothing' lazy
where
step_ mx a = Just' (case mx of
Nothing' -> a
Just' x -> step x a)
premap :: (a -> b) -> Fold b r -> Fold a r
premap f (Fold step begin done) = Fold step' begin done
where
step' x a = step x (f a)
premapM :: (a -> b) -> FoldM m b r -> FoldM m a r
premapM f (FoldM step begin done) = FoldM step' begin done
where
step' x a = step x (f a)
prefilter :: (a -> Bool) -> Fold a r -> Fold a r
prefilter f (Fold step begin done) = Fold step' begin done
where
step' x a = if f a then step x a else x
prefilterM :: (Monad m) => (a -> m Bool) -> FoldM m a r -> FoldM m a r
prefilterM f (FoldM step begin done) = FoldM step' begin done
where
step' x a = do
use <- f a
if use then step x a else return x
type Handler a b =
forall x . (b -> Const (Dual (Endo x)) b) -> a -> Const (Dual (Endo x)) a
handles :: Handler a b -> Fold b r -> Fold a r
handles k (Fold step begin done) = Fold step' begin done
where
step' = flip (appEndo . getDual . getConst . k (Const . Dual . Endo . flip step))
foldOver :: Handler s a -> Fold a b -> s -> b
foldOver l (Fold step begin done) =
done . flip appEndo begin . getDual . getConst . l (Const . Dual . Endo . flip step)
newtype EndoM m a = EndoM { appEndoM :: a -> m a }
instance Monad m => Semigroup (EndoM m a) where
(EndoM f) <> (EndoM g) = EndoM (f <=< g)
instance Monad m => Monoid (EndoM m a) where
mempty = EndoM return
mappend = (<>)
type HandlerM m a b =
forall x . (b -> Const (Dual (EndoM m x)) b) -> a -> Const (Dual (EndoM m x)) a
handlesM :: HandlerM m a b -> FoldM m b r -> FoldM m a r
handlesM k (FoldM step begin done) = FoldM step' begin done
where
step' = flip (appEndoM . getDual . getConst . k (Const . Dual . EndoM . flip step))
foldOverM :: Monad m => HandlerM m s a -> FoldM m a b -> s -> m b
foldOverM l (FoldM step begin done) s = do
b <- begin
r <- (flip appEndoM b . getDual . getConst . l (Const . Dual . EndoM . flip step)) s
done r
folded
:: (Contravariant f, Applicative f, Foldable t)
=> (a -> f a) -> (t a -> f (t a))
folded k ts = contramap (\_ -> ()) (F.traverse_ k ts)
filtered :: Monoid m => (a -> Bool) -> (a -> m) -> a -> m
filtered p k x
| p x = k x
| otherwise = mempty