2015-12-13 8 views
8

Ich habe eine kleine Haskell Pipe, die aus druckt, wie oft es gelaufen ist:Wie erkennt man den letzten Brocken in einer Haskell Pipe?

counterPipe :: Pipe String String IO r 
counterPipe = go 0 
    where 
    go n = do 
     await >>= yield 
     let n' = succ n 
     liftIO $ putStrLn $ "Chunk " ++ show n' 
     go n' 

Ich möchte in der Lage sein, eine Nachricht zu drucken, und möglicherweise andere Aufgaben ausführen, sobald es die letzten verarbeitet Stück. Wie gehe ich dabei vor?

Antwort

3

Ich konnte dies durch eine Änderung counterPipe ‚s-Eingangstyp Maybe String und Injizieren eines zusätzlichen Nothing nachdem das stromaufwärtige Rohr Oberflächen zu arbeiten erhalten:

import Pipes 
import Pipes.Core (respond) 
import Control.Applicative ((<*)) 

withEOF :: (Monad m) => Proxy a' a b' b m r -> Proxy a' a b' (Maybe b) m r 
withEOF p = for p (respond . Just) <* respond Nothing 

counterPipe :: Pipe (Maybe String) String IO Int 
counterPipe = go 0 
    where 
    go n = do 
     mx <- await 

     case mx of 
      Just x -> do 
       yield x 
       let n' = succ n 
       liftIO $ putStrLn $ "Chunk " ++ show n' 
       go n' 
      Nothing -> do 
       return n 

finishCounter :: Int -> Pipe a b IO() 
finishCounter n = liftIO $ putStrLn $ unwords ["Finished after", show n, "chunks"] 

Beispiel Fahrer:

import qualified Pipes.Prelude as P 
main = runEffect $ withEOF P.stdinLn >-> (counterPipe >>= finishCounter) >-> P.stdoutLn 

I denke, dass dieses Muster in etwas wie

whileJust :: (Monad m) => Proxy a' a b' b m r -> Proxy a' (Maybe a) b' b m (Maybe r) 
abstrahierbar sein sollte

so konnte man

withEOF P.stdinLn >-> (whileJust counterPipe >>= maybe (return()) finishCounter) >-> P.stdoutLn 

schreiben, ohne Ihre ursprüngliche counterPipe Definition ändern zu müssen; aber ich habe nie Pipes vorher verwendet (die obige Lösung wurde herausgefunden, indem Sie nur auf die Typen und spielen Typ-Domino) und so habe ich es nicht geschafft zu schreiben whileJust (die Unterschrift ist wahrscheinlich zu allgemein in Möglichkeiten, die ich nicht kann herausfinden).

Verwandte Themen