您幾乎在那裏;你只需要運行狀態。
main = do
bs <- L.unpack `fmap` L.getContents
flip execStateT 0 $ runEffect $ produceList bs >-> buzzHash >-> hoist lift stdoutLn
我假設你不想找回狀態,所以我用execStateT
而非runStateT
。
這裏唯一的好奇是stdoutLn
被標記爲Consumer Word64 IO()
。因此,我使用hoist lift
來製作它Consumer Word64 (StateT Word64 IO)()
系列a >-> b >-> c
中的所有內容都必須在基礎monad和返回類型中達成一致。
以下是一些可能爲您節省時間的進一步評論。第一個produceFromList
是each
。
此外,你可能會被重新標記您的stdoutLn
避免hoist lift
:
stdoutLn :: MonadIO m => Consumer Word64 m()
stdoutLn = do
a <- await
liftIO $ print a
但這裏有一些麻煩:你是不是重複的動作。這應該很清楚是一個循環:
stdoutLn :: MonadIO m => Consumer Word64 m()
stdoutLn = do
a <- await
liftIO $ print a
stdoutLn
其實這已經可以作爲P.print
,所以我們可以寫
import qualified Pipes.Prelude as P
main = do
bs <- L.unpack `fmap` L.getContents
flip execStateT 0 $ runEffect $ each bs >-> buzzHash >-> P.print
如果我理解你,buzzHash
意味着太無限期地重複:
buzzHash = do
x <- await
h <- lift $ get -- pull out previous value
let h' = rotate h 1 `xor` (hashArrW8!x) -- calculate new value
lift $ put h' -- save new value
yield h'
buzzHash
(這是forever buzzHash
,在這裏我們使用您的buzzHash
)
最後,如果你
import qualified Pipes.ByteString as PB
import Control.Lens (view) -- (or Lens.Micro.MTL or Lens.Simple)
我們看到我們不需要懶惰的字節串IO,不正確流反正。 Pipes.ByteString
已經有我們想要的unpack
,打包成鏡頭,以便我們在其他地方使用view PB.unpack
我們將使用B.unpack
。那麼到底我們可以寫
main = flip evalStateT 0 $ runEffect $ view PB.unpack PB.stdin >-> buzzHash >-> P.print
一旦處於這種形式,我們看到我們沒有使用管道的基本狀態,除了在buzzHash
,所以我們可以本地化此
import Pipes.Lift (evalStateP)
main = runEffect $ view PB.unpack PB.stdin >-> evalStateP 0 buzzHash >-> P.print
或如果你喜歡,你可以重寫
buzzHash' :: Monad m => Word64 -> Pipe Word8 Word64 m r
buzzHash' n = evalStateP n $ forever $ do
x <- await
h <- lift $ get -- pull out previous value
let h' = rotate h 1 `xor` (hashArrW8!x) -- calculate new value
lift $ put h' -- save new value
yield h'
然後你會寫
main = runEffect $ view PB.unpack PB.stdin >-> buzzHash' 0 >-> P.print
是在狀態monad中的'buzzHash'之後的所有內容? –
通過'> - >'全部轉換'(StateT Word64 IO)'鏈接的三個管道事件,是的。因此,'buzzHash'專門用於'管道Word8 Word64(StateT Word64 IO)()','P.print'專門用於'客戶端Word64(StateT Word64 IO)()'和'查看PB.unpack PB.stdin'到'Producer Word8(StateT Word64 IO)()'來使用類型同義詞管道使用。所以當你將它們並排在一起時,你會得到一個'Effect(StateT Word64 IO)()'。那麼,當你應用'runEffect'時,你會得到一個'StateT Word64 IO()'。接下來,當你應用'runStateT'時你有一個'Word64 - > IO((),Word64)'。 – Michael
我在最後加入了一些關於'evalStateP'等的內容。也許這更合適,因爲它不涉及調整管道,以便一切都一致。相反,我們只是編寫一個'buzzHash'函數,該類型中沒有明確涉及'StateT'。 – Michael