Следующий фрагмент кода испытывает переполнение стека для больших входов:Haskell избежать переполнения стека в складках без ущерба для производительности
{-# LANGUAGE DeriveDataTypeable, OverloadedStrings #-}
import qualified Data.ByteString.Lazy.Char8 as L
genTweets :: L.ByteString -> L.ByteString
genTweets text | L.null text = ""
| otherwise = L.intercalate "\n\n" $ genTweets' $ L.words text
where genTweets' txt = foldr p [] txt
where p word [] = [word]
p word [email protected](w:ws) | L.length word + L.length w <= 139 =
(word `L.append` " " `L.append` w):ws
| otherwise = word:words
Я предполагаю, что мой предикат строит список санков, но я не знаю, почему , или как его исправить.
Эквивалентный код с использованием foldl'
работает нормально, но берет навсегда, поскольку он постоянно добавляется и использует тонну памяти.
import Data.List (foldl')
genTweetsStrict :: L.ByteString -> L.ByteString
genTweetsStrict text | L.null text = ""
| otherwise = L.intercalate "\n\n" $ genTweetsStrict' $ L.words text
where genTweetsStrict' txt = foldl' p [] txt
where p [] word = [word]
p words word | L.length word + L.length (last words) <= 139 =
init words ++ [last words `L.append` " " `L.append` word]
| otherwise = words ++ [word]
Что вызывает первый сниппет, чтобы создать грозди, и его можно избежать? Можно ли написать второй фрагмент, чтобы он не полагался на (++)
?
Я вижу, как обход замедляет его. У меня сложилось впечатление, что складка уже создала список лениво. –