簡體   English   中英

使用管道解析來保留剩余的地圖

[英]Using pipes-parse to preserve leftovers with a map

我試圖理解splitAt -parse 3.0如何在spansplitAt之外的情況下工作,並且無法弄清楚如何使事情正常工作。 基本思想是我有一個同構,我想映射所有輸入值以從類型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 mrparser是一個Parser B m (Maybe B, [A], [B]) 我認為這樣做的核心是,在經過一些先前的解析操作之后,剩余的就是在Parser -State綁定的Producer發生的事情。 因此,您可以像平常一樣使用zoom來修改Producer無論您喜歡什么。

請注意,我們可以翻轉鏡頭的順序並進行zoom (piso (from ab) . Pp.splitAt 3) Pp.drawAll但是因為鏡頭從左向右下降意味着我們在關注之前修改整個Producer接下來的三個要素。 使用我的主要示例中的順序減少了AB之間的映射數。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM