Обычно рекомендуемые типы строк Haskell кажутся ByteString или Text. Я часто работаю с очень большим количеством коротких (английских размерных слов) строк и, как правило, должен хранить их в таблице поиска, такой как Data.Map. Во многих случаях я нахожу, что в этом сценарии таблица строк может занимать меньше памяти, чем таблица ByteStrings. Unboxed Data.Vectors of Word8 также (намного) более компактны, чем ByteStrings.
Какова наилучшая практика, когда нужно хранить и сравнивать большое количество небольших строк в Haskell?
Ниже я попытался сконфигурировать конкретный проблемный случай в небольшом примере:
import qualified Data.ByteString.Lazy.Char8 as S
import qualified Data.ByteString as Strict
import qualified Data.Map as Map
import qualified Data.Vector.Unboxed as U
import qualified Data.Serialize as Serialize
import Control.Monad.State
main = putStr
. unlines . map show . flip evalState (0,Map.empty)
. mapM toInt
. S.words
=<<
S.getContents
toInt x = do
let x' =
U.fromList . Strict.unpack . -- Comment this line to increase memory usage
Serialize.encode $ x
(i,t) <- get
case Map.lookup x' t of
Just j -> return j
Nothing -> do
let i' = i + (1::Int)
put (i', Map.insert x' i t)
return i
Когда я запускаю это в файле, содержащем около 400 000 слов текста на английском языке, версия со строгими ключами bytestring использует около 50 МБ памяти, одна с векторами Word8 использует 6 МБ.