Haskell tricky space overflow

流过昼夜 提交于 2020-01-04 09:03:37

问题


Running into a space overflow when trying to run this code (I've commented out the changes I've already tried):

{-# LANGUAGE BangPatterns #-}

import System.IO (hFlush, stdout)
import System.Environment (getArgs)
-- import Data.List (foldl')
import qualified Data.Map as Map
-- import qualified Data.Map.Strict as Map
-- import qualified Data.ByteString.Char8 as B


data Trie = Trie { isWord :: Bool, children :: Map.Map Char Trie }


initial :: Trie
initial = Trie False Map.empty


insertWord :: String -> Trie -> Trie
insertWord [] trie     = trie { isWord = True }
insertWord (c:cs) trie = trie { children = Map.insert c child $ children trie }
    where
      child = maybe (insertWord cs initial) (insertWord cs)
              (Map.lookup c (children trie))

-- insertWord :: String -> Trie -> Trie
-- insertWord [] trie     = trie { isWord = True }
-- insertWord (!c:(!cs)) trie = trie { children = Map.insert c child $ children trie }
--     where
--       child = let a = maybe (insertWord cs initial) (insertWord cs)
--                       (Map.lookup c (children trie))
--               in seq a a


fromWords :: [String] -> Trie
fromWords = foldr insertWord initial

-- fromWords :: [String] -> Trie
-- fromWords = foldl' (flip insertWord) initial


toWords :: Trie -> [String]
toWords = concatMap results . Map.toList . children
    where
      results (c, t) = (if isWord t then ([c]:) else id)
                       . map (\str -> c:str) $ toWords t


completions :: String -> Trie -> [String]
completions [] trie     = toWords trie
completions (c:cs) trie = maybe [] (map (c:) . completions cs)
                          (Map.lookup c $ children trie)


main :: IO ()
main = do
  [prefix] <- getArgs
  dict <- readFile "/usr/share/dict/words"
  mapM_ putStrLn (completions prefix (fromWords $ lines dict))
--  dict <- B.readFile "/usr/share/dict/words"
--  mapM_ putStrLn (completions prefix (fromWords $ map (B.unpack) $ B.lines dict))

Output:

$ ./trie abba
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.

The output from "+RTS -h": http://i.imgur.com/i3pdT7S.png

I can get the code to work if I specify "+RTS -K1G". I'd really appreciate if someone could point me in the right direction.


回答1:


You had the right idea with the commented-out foldl' approach -- you just need to make sure children is forced when a Trie is; i.e. make the children field in Trie strict.

data Trie = Trie { isWord :: Bool, children :: !(Map.Map Char Trie) }


来源:https://stackoverflow.com/questions/25129638/haskell-tricky-space-overflow

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!