module Control.Foldl (
Fold(..)
, FoldM(..)
, fold
, foldM
, scan
, Control.Foldl.mconcat
, Control.Foldl.foldMap
, head
, last
, lastDef
, lastN
, null
, length
, and
, or
, all
, any
, sum
, product
, maximum
, minimum
, elem
, notElem
, find
, index
, elemIndex
, findIndex
, random
, randomN
, sink
, genericLength
, genericIndex
, list
, revList
, nub
, eqNub
, set
, vector
, purely
, impurely
, generalize
, simplify
, duplicateM
, _Fold1
, premap
, premapM
, Handler
, handles
, EndoM(..)
, HandlerM
, handlesM
, 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.Constant (Constant(Constant, getConstant))
import Data.Functor.Identity (Identity, runIdentity)
import Data.Monoid
import Data.Profunctor
import Data.Sequence ((<|))
import Data.Vector.Generic (Vector, Mutable)
import Data.Vector.Generic.Mutable (MVector)
import System.Random.MWC (GenIO, createSystemRandom, uniformR)
import Prelude hiding
( head
, last
, null
, length
, and
, or
, all
, any
, sum
, product
, maximum
, minimum
, elem
, notElem
)
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.Vector.Generic as V
import qualified Data.Vector.Generic.Mutable as M
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 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 => Monoid (Fold a b) where
mempty = pure mempty
mappend = liftA2 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 sin
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) => 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 sin
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)
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 = a <| s'
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
maximum :: Ord a => Fold a (Maybe a)
maximum = _Fold1 max
minimum :: Ord a => Fold a (Maybe a)
minimum = _Fold1 min
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
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)
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
maxChunkSize :: Int
maxChunkSize = 8 * 1024 * 1024
vector :: (PrimMonad m, Vector v a) => FoldM m a (v a)
vector = 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
impurely
:: Monad m
=> (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
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)
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)
type Handler a b =
forall x . (b -> Constant (Endo x) b) -> a -> Constant (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 . getConstant . k (Constant . Endo . flip step))
newtype EndoM m a = EndoM { appEndoM :: a -> m a }
instance Monad m => Monoid (EndoM m a) where
mempty = EndoM return
mappend (EndoM f) (EndoM g) = EndoM (f >=> g)
type HandlerM m a b =
forall x . (b -> Constant (EndoM m x) b) -> a -> Constant (EndoM m x) a
handlesM :: Monad m => 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 . getConstant . k (Constant . EndoM . flip step))