2015-12-13 4 views
8

У меня есть небольшая Haskell Pipe, который печатает, сколько раз он побежал:Как обнаружить последний кусок в трубке Haskell?

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' 

Я хотел бы иметь возможность распечатать сообщение и потенциально выполнять другие задачи после того, как он обработал последний кусок. Как мне это сделать?

ответ

3

я смог получить эту работу путем изменений counterPipe «s типа входного сигнала на Maybe String и введение дополнительного Nothing после того, как выше по потоку концов трубы:

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"] 

Пример драйвер:

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

Я подумайте, что этот шаблон должен быть абстрагируемым чем-то вроде

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

так что вы могли бы написать

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

без необходимости изменения оригинального counterPipe определения; , но я никогда раньше не использовал Pipes (вышеприведенное решение было выяснено, просто глядя на типы и тип игры-домино), и поэтому мне не удалось написать whileJust (подпись, вероятно, слишком общая, так что я не могу выяснить).

Смежные вопросы