{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE BangPatterns #-}
import Data.List
import Control.Applicative
import Control.Arrow
dup :: a -> (a, a)
dup x = (x, x)
infixr 9 .*
(.*) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.*) = (.) . (.)
n !- m = let d = n - m in if d <= 0 then 0 else d
addToAcc :: c' -> (c, b) -> ((c, c'), b)
addToAcc x (acc, res) = ((acc, x), res)
infixr 5 $: , $++
infixr 9 $!!
newtype AccList a = AccList {runAccList :: forall b c.
Integer -> c
-> b
-> (c
-> a
-> (c
, b
-> b
)) -> b
}
fmap f xs
= pure f
<*> xs
instance Applicative AccList where
(<*>) = ap
instance Monad AccList
where
nil :: AccList a
nil = AccList $ \_ _ res _ -> res
($:) :: a -> AccList a -> AccList a
x $: xs = AccList $ \d acc res facc -> if d == 0
then let (acc', fres) = facc acc x in
fres $ runAccList xs 0 acc' res facc
else runAccList xs (d - 1) acc res facc
runAccListAccEnd :: AccList a -> forall b c.
Integer -> c
-> (c
-> (c
, b
)) -> (c
-> a
-> (c
, b
-> b
)) -> (c
, b
) runAccListAccEnd xs d acc end facc = ($ acc) $ runAccList xs d acc end $
\(!acc') x -> let (acc'', fres) = facc acc' x in (,) acc'' $
\end' -> let (acc''', res') = end' acc'' in
const (acc
''', fres res')
runAccListAcc :: AccList a -> forall b c.
Integer -> c
-> b
-> (c
-> a
-> (c
, b
-> b
)) -> (c
, b
) runAccListAcc xs d acc res facc =
runAccListAccEnd xs d acc
(flip (,) res
) facc
runAccListEnd :: AccList a -> forall b c.
Integer -> c
-> (c
-> b
) -> (c
-> a
-> (c
, b
-> b
)) -> b
runAccListEnd xs d acc end facc =
snd $ runAccListAccEnd xs d acc
(second end
. dup
) facc
ffromList
= foldr ($:
) nil
ftoList = ffoldr (:) []
-- Basic functions.
($++) :: AccList a -> AccList a -> AccList a
xs $++ ys = AccList $ \d acc res facc ->
let (acc', res') = runAccListAcc xs d acc
(runAccList ys (d !- flength xs) acc' res facc) facc
in res'
fhead :: AccList a -> a
flast :: AccList a -> a
flast xs
= fst $ runAccListAcc xs
0 (fhead xs
) () $ \
_ x
-> (x
, _u
)
ftail :: AccList a -> AccList a
ftail = fdrop 1
finit :: AccList a -> AccList a
finit xs = ftake (flength xs - 1) xs
fnull
:: AccList a
-> Boolfnull = ffoldr (\_ _ -> True) False
flength = ffoldl' (\r _ -> r + 1) 0
-- List transformations
ffmap :: (a -> b) -> AccList a -> AccList b
ffmap f xs = AccList $ \d acc res facc ->
runAccList xs d acc res $ \acc' -> facc acc' . f
freverse :: AccList a -> AccList a
freverse = ffoldl (flip ($:)) nil
-- fintersperse
-- fintercalate
-- ftranspose
fsubsequences :: AccList a -> AccList (AccList a)
fsubsequences = (nil $:) . f (\x -> (pure x $:) . f (\ys r -> ys $: (x $: ys) $: r))
where f = flip ffoldr nil
-- fpermutations
-- Reducing lists (folds)
ffoldl :: (b -> a -> b) -> b -> AccList a -> b
ffoldl f z xs = fst $ runAccListAcc xs 0 z () $ \res' x -> (f res' x, id)
ffoldl' :: (b -> a -> b) -> b -> AccList a -> b
ffoldl' f z xs = fst $ runAccListAcc xs 0 z () $ \(!res') x -> (f res' x, id)
-- ffoldl1
-- ffoldl1'
ffoldr :: (a -> b -> b) -> b -> AccList a -> b
ffoldr f z xs = runAccList xs 0 () z (\() x -> ((), f x))
-- Special folds
fconcat :: AccList (AccList a) -> AccList a
fconcat = ffoldr ($++) nil
fconcatMap :: (a -> AccList b) -> AccList a -> AccList b
fconcatMap = fconcat .* ffmap
fany
:: (a
-> Bool) -> AccList a
-> Boolfany p = ffoldr ((||) . p) False
fall
:: (a
-> Bool) -> AccList a
-> Boolfall p = ffoldr ((&&) . p) True
fsum
:: Num a
=> AccList a
-> a
fsum = ffoldl' (+) 0
fproduct :: Num a => AccList a -> a
fproduct = ffoldl' (*) 1
-- fmaximum
-- fminimum
-- Building lists
-- Scans
fscanl :: (b -> a -> b) -> b -> AccList a -> AccList b
fscanl f z xs = AccList $ \d acc res facc ->
let (z', _) = runAccListAcc (ftake d xs) 0 z res
(\z'' x -> (f z'' x, _u))
in runAccListEnd xs d (acc, z')
(\(acc', z'') -> ($ res) $ snd $ facc acc' z'')
(\(acc', z'') x -> addToAcc (f z'' x) $ facc acc' z'')
fscanl1 :: (a -> a -> a) -> AccList a -> AccList a
fscanl1 f xs = fscanl f (fhead xs) (ftail xs)
fscanr :: (a -> b -> b) -> b -> AccList a -> AccList b
-- fscanr1
-- Accumulating maps
fmapAccumL :: (c -> a -> (c, b)) -> c -> AccList a -> (c, AccList b)
fmapAccumL f z xs = runAccListAcc xs 0 z nil $ second ($:) .* f
fsndMapAccumL :: (c -> a -> (c, b)) -> c -> AccList a -> AccList b
fsndMapAccumL f z xs = AccList $ \d acc res facc ->
let (z', _) = runAccListAcc (ftake d xs) 0 z res $
\z'' x -> (fst $ f z'' x, _u)
in runAccList xs d (acc, z') res $
\(acc', z'') x -> let (z''', x') = f z'' x in
addToAcc z''' $ facc acc' x'
fmapAccumR :: (c -> a -> (c, b)) -> c -> AccList a -> (c, AccList b)
fmapAccumR f z = ffoldr (\x (z', xs') -> ($: xs') `second` f z' x) (z, nil)
-- Infinite lists
frepeat :: a -> AccList a
fiterate :: (a -> a) -> a -> AccList a
freplicate
:: Integer -> a
-> AccList a
freplicate n = ftake n . frepeat
fcycle :: AccList a -> AccList a
fcycle xs
| fnull xs
= error "Empty list"fcycle xs = xs' where xs' = xs $++ xs'
-- Unfolding
funfoldr :: (b -> Maybe (a, b)) -> b -> AccList a
funfoldr = ffromList .* unfoldr
-- Sublists
-- Extracting sublists
ftake :: Integer -> AccList a -> AccList a
ftake n xs = AccList $ \d acc res facc ->
runAccList xs d (acc, n - d) res $
\(acc', n') x -> if n' <= 0
then ((acc', 0), const res)
else addToAcc (n' - 1) $ facc acc' x
fdrop :: Integer -> AccList a -> AccList a
fdrop n xs = AccList $ \d -> runAccList xs (d + (n !- 0))
fsplitAt :: Integer -> AccList a -> (AccList a, AccList a)
fsplitAt n xs = (ftake n xs, fdrop n xs)
ftakeWhile :: (a -> Bool) -> AccList a -> AccList a
ftakeWhile p xs = AccList $ \d acc res facc ->
if fall p (ftake d xs)
then runAccList xs d acc res $
\acc' x
-> if p x
then facc acc
' x else (acc', const res
) else res
fdropWhile
:: (a
-> Bool) -> AccList a
-> AccList a
fdropWhile p xs = fdrop (flength (ftakeWhile p xs)) xs
-- fdropWhileEnd
fspan
:: (a
-> Bool) -> AccList a
-> (AccList a
, AccList a
)fspan p xs = (ftakeWhile p xs, fdropWhile p xs)
fbreak
:: (a
-> Bool) -> AccList a
-> (AccList a
, AccList a
)fbreak p
= fspan
(not . p
)
-- fstripPrefix
-- fgroup
finits :: AccList a -> AccList (AccList a)
finits
= ffoldr
(\x r
-> nil
$:
fmap (x
$:
) r
) (nil
$: nil
)
ftails :: AccList a -> AccList (AccList a)
ftails = ffoldr (\x r -> (x $: fhead r) $: r) (nil $: nil)
-- Predicates
-- fisPrefixOf
-- fisSuffixOf
-- fisInfixOf
-- Searching lists
-- Searching by equality
felem
:: Eq a
=> a
-> AccList a
-> Boolfelem = fany . (==)
fnotElem
:: Eq a
=> a
-> AccList a
-> BoolfnotElem = fall . (/=)
flookup
:: Eq a
=> a
-> AccList
(a
, b
) -> Maybe b
flookup k = ffoldr (\(k', x) r -> if k == k' then Just x else r) Nothing
-- Searching with a predicate
ffind = flistToMaybe .* ffilter
ffilter
:: (a
-> Bool) -> AccList a
-> AccList a
ffilter p xs = AccList $ \d acc res facc -> runAccList xs d acc res $
\acc' x -> if p x then facc acc' x else (acc', id)
fpartition :: (a -> Bool) -> AccList a -> (AccList a, AccList a)
fpartition p xs = (ffilter p xs, ffilter (not . p) xs)
-- fIndexing lists
($!!) :: AccList a -> Integer -> a
xs $!! n = fhead $ fdrop n xs
felemIndex :: Eq a => a -> AccList a -> Maybe Integer
felemIndex = ffindIndex . (==)
felemIndices :: Eq a => a -> AccList a -> AccList Integer
felemIndices = ffindIndices . (==)
ffindIndex :: (a -> Bool) -> AccList a -> Maybe Integer
ffindIndex = flistToMaybe .* ffindIndices
ffindIndices :: (a -> Bool) -> AccList a -> AccList Integer
ffindIndices p = fmap fst . ffilter (p . snd) . fenumerate
-- Maybe
flistToMaybe :: AccList a -> Maybe a
flistToMaybe = ffoldr (\x _ -> Just x) Nothing
-- Misc
fenumerate :: AccList a -> AccList (Integer, a)
fenumerate = fsndMapAccumL (\n x -> (n + 1, (n, x))) 0
---
fdefhead = ffoldr const
fpow n f x = iterate f x !! n
-- quadratic
fzipWith f xs ys = fsndMapAccumL
(\x's' y' -> (ftail x's', alt f (fhead x's') y')) x's y's
where (alt, x's, y's) = if flength xs < flength ys
then (flip, ys, xs)
else (id, xs, ys)
main = do
print $ sum $ fpow 5000 tail [1..10^6]
print $ fsum $ fpow 5000 ftail $ ffromList [1..10^6]
print $ take 10 $ drop 5 $ take 20 $ take 27 $ findIndices even $ drop 5 $ scanl (-) 2 $ take 40 $ drop 10 [1..]
print $ ftoList $ ftake 10 $ fdrop 5 $ ftake 20 $ ftake 27 $ ffindIndices even $ fdrop 5 $ fscanl (-) 2 $ ftake 40 $ fdrop 10 $ ffromList [1..]
print $ reverse $ take 10 $ drop 3 $ reverse $ take 28 $ filter even $ drop 5 $ snd $ mapAccumL (\x y -> (x+y, x*y)) 5 $ takeWhile (<= 30) $ take 40 $ drop 10 [1..]
print $ ftoList $ freverse $ ftake 10 $ fdrop 3 $ freverse $ ftake 28 $ ffilter even $ fdrop 5 $ fsndMapAccumL (\x y -> (x+y, x*y)) 5 $ ftakeWhile (<= 30) $ ftake 40 $ fdrop 10 $ ffromList [1..]
print $ sum $ reverse $ drop 60 $ reverse $ takeWhile (<= 10^3) $ take (10^10) $ dropWhile (<= 50) $ drop 30 [1..]
print $ fsum $ freverse $ fdrop 60 $ freverse $ ftakeWhile (<= 10^3) $ ftake (10^10) $ fdropWhile (<= 50) $ fdrop 30 $ ffromList [1..]
print $ drop 2 $ takeWhile (<= 6) $ concat $ subsequences $ dropWhile (<= 3) [1..10]
print $ ftoList $ fdrop 2 $ ftakeWhile (<= 6) $ fconcat $ fsubsequences $ fdropWhile (<= 3) $ ffromList [1..10]