[英]Using pipes-parse to preserve leftovers with a map
我試圖理解splitAt
-parse 3.0如何在span
和splitAt
之外的情況下工作,並且無法弄清楚如何使事情正常工作。 基本思想是我有一個同構,我想映射所有輸入值以從類型A
轉換為類型B
然后,我想把所有剩菜從B
轉換回A
我如何在pipes-parse
實現這一目標?
為了比較,代碼在conduit
看起來如下:
import Control.Applicative ((<$>), (<*>))
import Data.Conduit (yield, ($$), (=$=))
import Data.Conduit.Extra (fuseLeftovers)
import qualified Data.Conduit.List as CL
newtype A = A Int
deriving Show
newtype B = B Int
deriving Show
atob (A i) = (B i)
btoa (B i) = (A i)
main :: IO ()
main = do
let src = mapM_ (yield . A) [1..10]
res <- src $$ (,,,)
<$> fuseLeftovers (map btoa) (CL.map atob) CL.peek
<*> CL.take 3
<*> (CL.map atob =$= CL.take 3)
<*> CL.consume
print res
編輯 :澄清一下,這是我上面代碼的輸出:
(Just (B 1),[A 1,A 2,A 3],[B 4,B 5,B 6],[A 7,A 8,A 9,A 10])
請注意,原始流是A
類型。 我們轉換為B
並在第一個元素上偷看,然后將接下來的3個元素作為A
,然后將以下三個元素作為B
,最后將余數作為A
我是通過引入輔助鏡頭組合器, piso :: Iso' ab -> Iso' (Producer amr) (Producer bmr)
import Control.Applicative
import Control.Lens (view, from, zoom, iso, Iso')
import Control.Monad.State.Strict (evalState)
import Pipes
import Pipes.Core as Pc
import qualified Pipes.Parse as Pp
import qualified Pipes.Prelude as P
newtype A = A Int
deriving Show
newtype B = B Int
deriving Show
atob (A i) = B i
btoa (B i) = A i
ab :: Iso' A B
ab = iso atob btoa
piso :: Monad m => Iso' a b -> Iso' (Producer a m r) (Producer b m r)
piso i = iso (P.map (view i) <-<) (>-> P.map (view $ from i))
main :: IO ()
main = do
let src = P.map atob <-< P.map A <-< each [1..10]
let parser = (,,) <$> zoom (Pp.splitAt 1) Pp.peek
<*> zoom (Pp.splitAt 3 . piso (from ab)) Pp.drawAll
<*> Pp.drawAll
let res = evalState parser src
print res
這里src
是一個Producer B mr
, parser
是一個Parser B m (Maybe B, [A], [B])
。 我認為這樣做的核心是,在經過一些先前的解析操作之后,剩余的就是在Parser
-State綁定的Producer
發生的事情。 因此,您可以像平常一樣使用zoom
來修改Producer
無論您喜歡什么。
請注意,我們可以翻轉鏡頭的順序並進行zoom (piso (from ab) . Pp.splitAt 3) Pp.drawAll
但是因為鏡頭從左向右下降意味着我們在關注之前修改整個Producer
接下來的三個要素。 使用我的主要示例中的順序減少了A
和B
之間的映射數。
view (Pp.splitAt 3 . piso (from ab))
:: Monad m => Producer B m x -> (Producer A m (Producer B m x))
-- note that only the outer, first Producer has been mapped over, the protected,
-- inner producer in the return type is isolated from `piso`'s effect
view (piso (from ab) . Pp.splitAt 3)
:: Monad m => Producer B m x -> (Producer A m (Producer A m x))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.