【发布时间】:2016-12-05 04:04:01
【问题描述】:
每当我考虑学习一门新语言(在这种情况下为 haskell)时,我都会尝试将原始 grep 克隆组合在一起,以查看语言实现和/或其库在文本处理方面的表现如何,因为这是一个主要用例对我来说。
受code on the haskell wiki的启发,我想出了以下幼稚的尝试:
{-# LANGUAGE FlexibleContexts, ExistentialQuantification #-}
import Text.Regex.PCRE
import System.Environment
io :: ([String] -> [String]) -> IO ()
io f = interact (unlines . f . lines)
regexBool :: forall r l .
(RegexMaker Regex CompOption ExecOption r,
RegexLike Regex l) =>
r -> l -> Bool
regexBool r l = l =~ r :: Bool
grep :: forall r l .
(RegexMaker Regex CompOption ExecOption r, RegexLike Regex l) =>
r -> [l] -> [l]
grep r = filter (regexBool r)
main :: IO ()
main = do
argv <- getArgs
io $ grep $ argv !! 0
这似乎在做我想做的事,但不幸的是,它真的很慢——比执行相同操作的 python 脚本慢大约 10 倍。我认为这不是正则表达式库的问题,因为它调用 PCRE 应该非常快(切换到 Text.Regex.Posix 会进一步减慢速度)。所以它一定是String 实现,从理论的角度来看这是有启发性的,但根据我所读到的,它是低效的。
haskell 中是否有一个替代 Strings 的替代方案,既高效又方便(即切换到使用它而不是 Strings 时几乎没有摩擦),并且可以完全正确地处理 UTF-8 编码的 Unicode ,以及其他没有太多麻烦的编码,如果可能的话?每个人在 haskell 中进行文本处理时都会使用的东西,但我只是不知道,因为我是一个完整的初学者?
【问题讨论】:
-
使用Text
-
只是想指出获得类似 C 的速度是可能的,但可能需要一些努力。看看 cgrep - awgn.github.io/cgrep
-
String是一个低性能的惰性字符串,它对于基本的短字符串“很好”,但不适合严重的文本操作。Text是用于 Unicode 文本操作的高性能类型。 (还有ByteString,它不是用于文本,而是用于字节序列。) -
你在编译优化吗?
-
@amalloy:我不知道优化,感谢您向我指出!不幸的是,在这种特殊情况下,差异似乎可以忽略不计......