{-# LANGUAGE ScopedTypeVariables,BangPatterns #-}
import qualified Data.Attoparsec.Internal as I
import qualified Data.Attoparsec.Internal.Types as T
import qualified Data.Vector.Unboxed as UVec
import qualified Data.Vector.Unboxed.Mutable as UMVec
import qualified Data.Vector as Vec
import qualified Data.Vector.Mutable as MVec
import qualified Data.Text as Text
import qualified System.IO.Unsafe as Unsafe
import Control.Monad.ST
import Control.Monad.Primitive
type Parser = T.Parser
manyCPSVec :: Parser Text.Text Char -> Parser Text.Text (Vec.Vector Char)
manyCPSVec parser = T.Parser $ \t pos more lose_fin win_fin ->
let arr = Unsafe.unsafePerformIO (MVec.new 1024) in
loop 0 arr t pos more lose_fin win_fin where
loop i (arr :: MVec.MVector RealWorld Char) t pos more lose_fin win_fin =
T.runParser parser t pos more lose win where
win t !pos more (a :: Char) =
Unsafe.unsafePerformIO (MVec.write arr i a) -- Here is the problem
loop (i+1) arr t pos more lose_fin win_fin
lose t pos more _ _ =
--x <- Vec.freeze arr
win_fin t pos more (Vec.empty)
main = print "Hello"
効率化のために Attoparsecにいくつかの機能を入れようとしてVector
いますが、壁にぶつかりました。
Attoparsec が CPS を使用して書かれていなければ、機能的な unfoldrを使用できたかもしれませんが、それはここではオプションではありません。問題は、ここではすべての呼び出しが末尾の位置にある必要があり、標準的な意味で関数が返されないため、配列をアキュムレータとして渡す必要があることです。
STモナドを使ってこれをやろうとしましたが、それがうまくいかなかったときは上記を試しましたが、それでもうまくいきません。ここでは、Haskell の型システムに本当に悩まされています。CPSでプログラミングするときに可変配列を編集することはとにかく可能ですか?
STモナド内でこれを行うことが可能であれば、私はこれを二重に感謝します.
ただし、配列以外のデータ構造を使用するように指示する投稿には反対票が投じられます。