2014-07-09 108 views
2
等效代碼

比方說,我有以下幾種類型:管材簡單的功能

type LinkID = Int 

data Link = Link { 
    lid :: LinkID, 
    llength :: Int 
    } 

data Snap = Snap { 
    slid :: LinkID, 
    slength :: Int 
    } 

現在,我想寫一個管道基礎功能,做到這一點:

getSnaps :: LinkID -> [Link] -> [Snap] -> [(LinkID, [Snap])] 
getSnaps l lks snp = map (\x -> (lid x, filter (\y -> lid x == slid y) snp)) a 
    where a = filter (\x -> lid x > l) lks 

Assumming,我已經有生產者LinkSnap,我如何在這兩個生產者的管道世界中實現上述getSnaps功能:

psnap :: Producer Snap IO() 
psnap = undefined 

plink :: Producer Link IO() 
plink = undefined 

psnapplink的實際類型涉及更多(使用attoparsec-pipes創建),但我想知道如何從psnapplink實現getSnap的功能。有沒有合適的方法來解決這類問題?

回答

2

我想出的解決方案非常類似於您的代碼。我剛剛更換mapPipes.Prelude.map和過濾器之一,Pipes.Prelude.filter

import Pipes 
import qualified Pipes.Prelude as Pipes 

type LinkID = Int 

data Link = Link 
    { lid :: LinkID 
    , llength :: Int 
    } 

data Snap = Snap 
    { slid :: LinkID 
    , slength :: Int 
    } 

getSnaps 
    :: Monad m 
    => LinkID 
    -> Producer Link   m() 
    -> Producer Snap   m() 
    -> Producer (LinkID, [Snap]) m() 
getSnaps l lks snp = do 
    snp' <- lift (Pipes.toListM snp) -- Cache `snp` into the list `snp'` 
    lks >-> Pipes.filter (\x -> lid x > l) 
     >-> Pipes.map (\x -> (lid x, filter (\y -> lid x == slid y) snp')) 

注意,有一個不平凡的一部分,這是上述方案嚴格加載snpProducer的內容到列表snp'。原因是我們必須反覆使用列表的內容,所以我們需要將整個列表緩存在內存中以便重複使用。