{-# 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"
I am trying to put in some Vector functionality in Attoparsec for efficiency, but I've run into a wall.
If Attoparsec was not written using CPS, I could have used a functional unfoldr, but that is not an option here. The problem is that all calls have to be in the tail position here and no function returns in the standard sense of the thing therefore arrays have to be passed along as accumulators.
I tried to do this using the ST monad, but when that did not work I tried the above, but even so it fails to work. Haskell's type system is really killing me here. Is it in anyway possible to edit mutable arrays when programming with CPS?
If it is possible to do this within the ST monad I would doubly appreciate this.
Posts telling me to use data structures other than arrays though, will be downvoted.
Vector.fromList? - MichaelST. The challenge will be dealing efficiently with partial results, but I suspect there is no entirely efficient way to handle those. In particular, remember that a partial result may be resumed multiple times with different inputs, so too muchunsafePerformIOcould break your code. - dfeuerResizeArrayin F# does it in 1.2s. The persistent vector does it in 9.8. Apart from the F# solution, they all blow the heap on 100M. Lists do that long before 10M. - Marko GrdinićInts, I think a parsing library might be too fancy.Data.ByteString.Char8.readIntis very fast. - Michael