gpt4 book ai didi

haskell - Get Monad 中的 IO

转载 作者:IT王子 更新时间:2023-10-29 05:58:29 24 4
gpt4 key购买 nike

所以我的问题如下。我正在尝试为 RDB 文件(Redis 生成的转储文件)实现流式解析器。我想实现一个类似于 mapM_ 的函数,我可以说打印出转储文件中表示的每个对象,因为它被解析。但是,我似乎无法让它在恒定空间中运行。我发现正在发生的事情是我在 Get monad 内部构建一个大的 IO() thunk,从 Get monad 返回然后执行 IO。有没有办法在我的对象被解析打印时流式传输然后丢弃它们?我已经尝试过 Enumerators 和 Conduits,但我没有看到任何真正的收获。这是我目前所拥有的:

loadObjs_ :: (Monad m) => (Maybe Integer -> BL8.ByteString -> RDBObj -> Get (m a)) -> Get (m a)
loadObjs_ f = do
code <- lookAhead getWord8
case code of
0xfd -> do
skip 1
expire <- loadTime
getPairs_ f (Just expire)
0xfc -> do
skip 1
expire <- loadTimeMs
getPairs_ f (Just expire)
0xfe -> f Nothing "Switching Database" RDBNull
0xff -> f Nothing "" RDBNull
_ -> getPairs_ f Nothing

getPairs_ :: (Monad m) => (Maybe Integer -> BL8.ByteString -> RDBObj -> Get (m a)) -> Maybe Integer -> Get (m a)
getPairs_ f ex = do
!t <- getWord8
!key <- loadStringObj False
!obj <- loadObj t
!rest <- loadObjs_ f
!out <- f ex key obj
return (out >> rest)


(loadObj does the actual parsing of a single object but I believe that whatever I need to fix the streaming to operate in constant or near-constant memory is at a higher level in the iteration than loadObj)

getDBs_ :: (Monad m) => (Maybe Integer -> BL8.ByteString -> RDBObj -> Get (m a)) -> Get (m a)
getDBs_ f = do
opc <- lookAhead getWord8
if opc == opcodeSelectdb
then do
skip 1
(isEncType,dbnum) <- loadLen
objs <- loadObjs_ f
rest <- getDBs_ f
return (objs >> rest)
else f Nothing "EOF" RDBNull

processRDB_ :: (Monad m) => (Maybe Integer -> BL8.ByteString -> RDBObj -> Get (m a)) -> Get (m a)
processRDB_ f = do
header <- getBytes 9
dbs <- getDBs_ f
eof <- getWord8
return (dbs)

printRDBObj :: Maybe Integer -> BL8.ByteString -> RDBObj -> Get (IO ())
printRDBObj (Just exp) key obj = return $ (print ("Expires: " ++ show exp) >>
print ("Key: " ++ (BL8.unpack key)) >>
print ("Obj: " ++ show obj))
printRDBObj Nothing key RDBNull = return $ (print $ BL8.unpack key)
printRDBObj Nothing key obj = return $ (print ("Key: " ++ (BL8.unpack key)) >>
print ("Obj: " ++ show obj))


main = do
testf <- BL8.readFile "./dump.rdb"
runGet (processRDB_ printRDBObj) testf

提前致谢。

最好的,埃里克

编辑:这是我尝试将对象解析为惰性列表,然后在惰性列表上进行 IO。

processRDB :: Get [RDBObj]

processRDB = do
header <- getBytes 9
dbs <- getDBs
eof <- getWord8
return (dbs)

main = do
testf <- BL8.readFile "./dump.rdb"
mapM_ (print . show) $ runGet processRDB testf

最佳答案

如果我对您的代码的理解正确,那么您正在尝试将文件内容逐步转换为 IO 操作,以期逐步执行这些操作。

更好的方法是让您的解析器返回一个惰性对象列表,然后您将其打印出来。

关于haskell - Get Monad 中的 IO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9689129/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com