这是我想出来的。
我使用了JB提供的功能,并添加了我从bytestring-lexing的源代码中学到的两个技巧(谢谢,sclv!)。第一个是这样的功能:
strict = SB.concat . LB.toChunks
它把一个懒惰字节串到非延迟一个有效。
第二个技巧是函数Data.ByteString.Internal.inlinePerformIO
,它是unsafePerformIO的一个更高效的变体。
下面是完整的代码,允许一个相当快的数字阅读:
{-# LANGUAGE ForeignFunctionInterface #-}
import qualified Data.ByteString.Lazy.Char8 as LB
import qualified Data.ByteString as SB
import Data.ByteString.Internal (inlinePerformIO)
import Foreign.C.String (CString)
import Foreign.C (CDouble)
import Data.Maybe (fromJust)
foreign import ccall unsafe "stdlib.h atof" c_atof :: CString -> IO Double
unsafeReadDouble = inlinePerformIO . flip SB.useAsCString c_atof
{-# INLINE unsafeReadDouble #-}
readDouble = unsafeReadDouble . SB.concat . LB.toChunks
readInt = fst . fromJust . LB.readInt
这计算输入所有数字的总和示例程序:
main = LB.getContents >>= (print . sum . map readDouble . LB.lines)
It processes an 11Mb file (1M numbers) in about 0.5 seconds
I also found several links , where a much more efficient version of readInt
进行了讨论。据推测,人们可以根据类似的想法建立一个readDouble
。但是我想现在我会坚持使用我目前的版本。
只需安装字节串,词法分析器包即可。 “cabal install bytestring-lexer” – sclv 2010-12-20 16:41:01
我想在没有附加包的情况下执行操作,因为我的程序将在我无法控制的服务器上运行。 – adamax 2010-12-20 18:34:20
@adamax:值得向你的问题添加限制。 – 2010-12-20 20:36:29