haskell写大字符串

haskell写大字符串,haskell,Haskell,大家好,我的社区 我对Haskell比较陌生,我注意到用 writeFile或hPutStr非常慢 对于1.5MB的字符串,我的程序(用ghc编译)大约需要2秒钟,而 C++中的“相同”代码只需0.1秒。 该字符串由一个包含大约10000个元素的列表生成,然后用writeFile转储。我还尝试使用mapM和hPutStr遍历列表,结果相同 有没有写大字符串的更快的方法 更新 正如@applicative所指出的,下面的代码很快就会以2MB文件结束 main = readFile "input.t

大家好,我的社区

我对Haskell比较陌生,我注意到用
writeFile
hPutStr
非常慢

对于1.5MB的字符串,我的程序(用ghc编译)大约需要2秒钟,而 C++中的“相同”代码只需0.1秒。 该字符串由一个包含大约10000个元素的列表生成,然后用
writeFile
转储。我还尝试使用
mapM
hPutStr
遍历列表,结果相同

有没有写大字符串的更快的方法

更新

正如@applicative所指出的,下面的代码很快就会以2MB文件结束

main = readFile "input.txt" >>= writeFile "ouput.txt"
所以我的问题似乎在别的地方。下面是我的两个实现 编写列表(WordIndex和CoordList是映射和列表的类型别名)

使用hPutStrLn

-- Print to File
indexToFile :: String -> WordIndex -> IO ()
indexToFile filename index =
    let 
        indexList = map (\(k, v) -> entryToString k v)  (Map.toList index)
    in do
        output <- openFile filename WriteMode
        mapM_ (\v -> hPutStrLn output v) indexList
        hClose output


-- Convert Listelement to String
entryToString :: String -> CoordList -> String
entryToString key value = (embedString 25 key) ++ (coordListToString value) ++ "\n"
也许你们能帮我找到一个加速点


提前谢谢

是的。例如,您可以使用模块
Data.Text
Data.Text.Lazy
中的
Text
类型,它们在内部以比字符列表更有效的方式表示文本(即UTF-16)

在编写二进制数据(可能包含也可能不包含以某种形式编码的文本)时,可以使用
ByteString
s或它们的等价物


当修改
文本
ByteStrings
时,在惰性版本上修改它们的一些操作会更快。如果您只想在创建字符串后读取该字符串,通常建议使用非惰性版本。

这是一个众所周知的问题。默认的Haskell
String
类型是simple
[Char]
,根据定义,它的速度很慢,如果它是惰性构造的(通常情况下),则它的速度非常慢。然而,作为列表,它允许使用列表组合器进行简单而干净的处理,并且在性能不是问题时非常有用。如果是,则应使用
ByteString
Text
ByteString
更好,因为它与ghc一起提供,但不提供unicode支持<基于代码>ByteString的utf8软件包在hackage上提供

字符串包含什么类型的内容
ByteString
的写入速度是最快的,所以如果你能便宜地转换成
ByteString
,那将是一种选择<代码>主文件=“读文件”“1.5 Mb.txt”> =写文件“1.5 Mb2.txt”<代码>使用<代码> 0M0.089S 这里,不是2秒,因此比您报告的C++更快。在大约50MB时,它开始接近2秒;类似地,
writeFile“big.txt”(show[1..250000])
需要0.06秒,生成一个1.6MB的文件。你是对的@applicative我的问题似乎在其他地方。我将发布一些代码请提供足够的代码,我们可以编译、运行并观察两秒钟的暂停。
-- Print to File
indexToFile :: String -> WordIndex -> IO ()
indexToFile filename index = writeFile filename (indexToString "" index)

-- Index to String
indexToString :: String -> WordIndex -> String
indexToString lead index = Map.foldrWithKey (\k v r -> lead ++ (entryToString k v) ++ r) "" index