Почему такой код (`par` из пакета `parallel`):
foldChunks :: (b -> b -> b) -> ([a] -> b) -> [[a]] -> b
foldChunks g f xs =
case xs of
[] -> f []
(xs:xss) ->
let rest = foldChunks g f xss
in rest `par` (f xs `g` rest)
выполняется так же долго как и
foldChunksPlain :: (b -> b -> b) -> ([a] -> b) -> [[a]] -> b
foldChunksPlain g f = foldr (g . f) (f [])
если вызвать как
foldChunks (<>) (Sum . sum) xs
или
foldChunksPlain (<>) (Sum . sum) xs
а такой - в разы быстрее:
foldChunksMon :: Monoid b => ([a] -> b) -> [[a]] -> b
foldChunksMon f xs =
case xs of
[] -> f []
(xs:xss) ->
let rest = foldChunksMon f xss
in rest `par` (f xs <> rest)
Казалось бы, всего лишь поменял
<>
на
g
, а параллелизм судя по всему исчез 👀