甚至超過pipes-parse
你很可能想看看pipes-group
。尤其是,讓我們來看看功能
-- this type is slightly specialized
chunksOf
:: Monad m =>
Int ->
Lens' (Producer a m x) (FreeT (Producer a m) m x)
的Lens'
位也許是可怕的,但可以很快被淘汰:它指出我們可以轉換Producer a m x
至FreeT (Producer a m) m x
[0]
import Control.Lens (view)
chunkIt :: Monad m => Int -> Producer a m x -> FreeT (Producer a m) m x
chunkIt n = view (chunksOf n)
所以現在我們要弄清楚該怎麼做FreeT
位。特別是,我們會想挖到free
包並拉出功能iterT
iterT
:: (Functor f, Monad m) =>
(f (m a) -> m a) ->
(FreeT f m a -> m a)
此功能,iterT
,讓我們「消費」一次一個FreeT
一個「臺階」。要理解這一點,我們首先專注的iterT
類型與Producer a m
runChunk :: Monad m =>
(Producer a m (m x) -> m x) ->
(FreeT (Producer a m) m x -> m x)
runChunk = iterT
特別是更換f
,runChunk
可以在「運行」一FreeT
充分的Producer
這麼只要我們告訴它如何轉換Producer a m (m x)
進入m
-action。 這可能會開始看起來更熟悉。當我們定義第一個參數runChunk
時,我們只需執行一個Producer
,在這種情況下,它將不會超過所選數量的元素。
但是,有效的返回值m x
是怎麼回事?這是「延續」,例如之後之後的所有塊。所以,舉例來說,假設我們有Char
的Producer
A S,我們希望經過3個字符
打印和換行符 main :: IO()
main = flip runChunk (chunkIt 3 input) $ \p -> _
在這一點上_
孔具有在上下文類型IO()
與p
鍵入p :: Producer Char IO (IO())
。我們可以使用for
來使用這個管道,收集它的返回類型(這是繼續,再次),發出一個換行符,然後運行延續。
input :: Monad m => Producer Char m()
input = each "abcdefghijklmnopqrstuvwxyz"
main :: IO()
main = flip runChunk (chunkIt 3 input) $ \p -> do
cont <- runEffect $ for p (lift . putChar)
putChar '\n'
cont
,並根據需要
λ> main
abc
def
ghi
jkl
mno
pqr
stu
vwx
yz
要清楚,而我做了一些闡述的這種行爲完全,這是相當簡單的代碼,一旦你看到所有的部分是如何結合在一起的。以下是整個列表:
input :: Monad m => Producer Char m()
input = each "abcdefghijklmnopqrstuvwxyz"
main :: IO()
main = flip iterT (input ^. chunksOf 3) $ \p -> do
cont <- runEffect $ for p $ \c -> do
lift (putChar c)
putChar '\n'
cont
[0]還有一點,但現在已經足夠了。