我正在使用該streaming軟體包。我想S.store通過保留常量記憶體來使用由 定義的一個步驟的結果作為管道中后續步驟的引數。從檔案中myStream加載和決議。
我有一個型別檢查的以下示例:
import qualified Streaming.Prelude as S
import qualified Data.Map.Strict as M
data A = MkA deriving (Show)
insertA :: MonadIO m => S.Stream (S.Of A) m r -> m (M.Map String Int)
insertA = undefined
insertB :: MonadIO m => M.Map String Int -> S.Stream (S.Of A) m r -> m Int
insertB = undefined
myStream :: S.Stream (S.Of A) IO r
myStream = undefined
run :: IO ()
run =
myStream
& S.store insertA
& insertB M.empty
& print
但是,該行& insertB M.empty正在使用一個空地圖,但我想從insertA函式中使用上一步中的地圖。然后該insertB函式使用此 Map 進行查找。
我能想到的解決方案如下:
run :: IO ()
run =
myStream
& S.store insertA
& ( \e -> do
resultMap <- S.effects e
insertB resultMap e
)
& print
問題
這是否保留了流媒體的好處,比如在恒定記憶體中運行?它如何在后臺解決這個問題,因為需要將流作為一個整體進行處理才能獲得Map?它多次傳遞同一個流 - 從檔案中加載它 2 次以保留常量記憶體?
如果是這種情況(加載檔案 2 次),如果流的源不是來自決議檔案,而是來自某些只能讀取一次的資料流,該怎么辦?
對于這個問題,是否還有其他優雅的解決方案也具有流式傳輸的好處,管道中的下一步需要使用上一步的結果?
uj5u.com熱心網友回復:
這里建議的代碼有問題:
resultMap <- S.effects e
insertB resultMap e
問題是您兩次“運行”同一個流,這對于基于流的流通常是有問題IO的。
例如,假設myStream從檔案句柄中讀取。當我們呼叫insertB第二遍時,effects已經到達檔案末尾!從句柄進行的任何進一步讀取都不會回傳任何資料。
當然,我們可以用兩個不同的流讀取同一個檔案兩次。這保留了流媒體,但需要兩次通過。
應該注意的是,對于某些具有內置資源管理的基本 monad,例如resourcet,您可以運行相同的Stream值兩次,因為流代碼足夠“智能”,可以在每次流時分配和釋放底層資源跑步。
例如,linear-base中存在的Stream型別版本支持函式:readFile
readFile :: FilePath -> Stream (Of Text) RIO ()
它回傳一個Stream在資源感知IO中作業。
也就是說,我不喜歡在流管道中隱藏對檔案的重復讀取,這讓我感到困惑。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/427272.html
