ここで私が思いついたのです。
私はJBによって提供される機能を使用し、私はbytestring-lexing(thanks、sclv!)のソースコードから学んだ2つのトリックを追加しました。最初の関数は次のとおりです。
strict = SB.concat . LB.toChunks
これは、遅延レイアウを非レイジーに効率的に変換します。
第2のトリックは、unsafePerformIOのより効率的な変種である機能Data.ByteString.Internal.inlinePerformIO
です。
{-# 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
私のプログラムは私が制御できないサーバー上で動くので、私は追加のパッケージなしでやりたい。 – adamax
@adamax:あなたの質問にその制限を加える価値があります。 –