2015-12-13 3 views
8

मैं एक छोटे से हास्केल 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' 

मैं एक संदेश बाहर मुद्रित करने के लिए, और संभवतः अन्य कार्य करने में सक्षम होना चाहते हैं एक बार यह पिछले संसाधित हिस्सा। मैं यह कार्य कैसे करूं?

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 

मैं

उत्तर

3

मैं इस नदी के ऊपर पाइप पूर्ण होने के बाद Maybe String को counterPipe के इनपुट प्रकार बदल रहा है और इंजेक्शन लगाने के लिए एक अतिरिक्त Nothing से काम करने के लिए प्राप्त करने में सक्षम था लगता है कि इस पैटर्न को

whileJust :: (Monad m) => Proxy a' a b' b m r -> Proxy a' (Maybe a) b' b m (Maybe r) 
जैसे कुछ में अमूर्त होना चाहिए

तो आप अपने मूल counterPipe परिभाषा को बदलने के लिए बिना

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

लिख सकता है; लेकिन मैंने कभी भी Pipes का उपयोग नहीं किया है (ऊपर दिए गए समाधान को केवल प्रकारों को देखकर और टाइप-डोमिनोज़ खेलकर पता लगाया गया था) और इसलिए मैंने whileJust लिखने में कामयाब नहीं रहा है (हस्ताक्षर शायद उन तरीकों से सामान्य है जो मैं नहीं कर सकता अंदाजा लगाओ)।

संबंधित मुद्दे