3

spanと以外のケースで pipes-parse 3.0 がどのように機能するかを理解しようとしていますsplitAtが、うまく機能させる方法がわかりません。基本的な考え方は、私には同型性があり、すべての入力値をマップして type から type に変換したいということAですBB次に、すべての残り物を からに戻したいと思い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 つの要素を type としてA取得し、次の 3 つを としてB取得し、最後に残りを として取得しAます。

4

1 に答える 1

3

補助レンズコンビネータを導入することで実現しましたが、piso :: Iso' a b -> Iso' (Producer a m r) (Producer b m r)

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に aProducer B m rparseraがありParser B m (Maybe B, [A], [B])ます。これの核心は、残り物は、事前の解析アクションの後にParserバインドされた -Stateで発生するものであるということだと思います。Producerしたがって、通常どおりに使用zoomして、好きなように変更Producerできます。

レンズの順序を反転して行うこともできますzoom (piso (from ab) . Pp.splitAt 3) Pp.drawAllが、レンズは左から右に下降するためProducer、次の 3 つの要素に焦点を合わせる前に全体を変更していることに注意してください。私の主要な例の順序を使用すると、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))
于 2014-02-08T19:21:52.010 に答える