खोज…


टिप्पणियों

हैकेज पेज का वर्णन के रूप में:

पाइप एक साफ और शक्तिशाली स्ट्रीम प्रोसेसिंग लाइब्रेरी है जो आपको पुन: प्रयोज्य स्ट्रीमिंग घटकों को बनाने और कनेक्ट करने देती है

स्ट्रीमिंग के माध्यम से कार्यान्वित किए जाने वाले कार्यक्रम अक्सर सरल और संक्षिप्त हो सकते हैं, हास्केल प्रकार प्रणाली के समर्थन के साथ सरल, छोटे फ़ंक्शन आपको "स्लॉट इन या आउट" सुविधाओं की अनुमति देते हैं।

await :: Monad m => Consumer' ama

अपस्ट्रीम से एक मान खींचता है, जहां a हमारे इनपुट प्रकार है।

yield :: Monad m => a -> Producer' am ()

एक मान उत्पन्न करें, जहां a आउटपुट प्रकार है।

यह अत्यधिक अनुशंसा की जाती है कि आप एम्बेडेड Pipes.Tutorial माध्यम से पढ़ें। Pipes.Tutorial पैकेज जो पाइप की मुख्य अवधारणाओं और Producer , Consumer और Effect बातचीत का एक उत्कृष्ट अवलोकन देता है।

प्रोड्यूसर्स

एक Producer कुछ विवादास्पद कार्रवाई है जो डाउनस्ट्रीम खपत के लिए मूल्य yield कर सकता yield :

type Producer b = Proxy X () () b
yield :: Monad m => a -> Producer a m ()

उदाहरण के लिए:

naturals :: Monad m => Producer Int m ()
naturals = each [1..] -- each is a utility function exported by Pipes

हम निश्चित रूप से Producer कि अन्य मूल्यों के कार्य भी कर सकते हैं:

naturalsUntil :: Monad m => Int -> Producer Int m ()
naturalsUntil n = each [1..n]

उपभोक्ताओं

एक Consumer केवल अपस्ट्रीम से मूल्यों का await कर सकता है।

type Consumer a = Proxy () a () X
await :: Monad m => Consumer a m a

उदाहरण के लिए:

fancyPrint :: MonadIO m => Consumer String m ()
fancyPrint = forever $ do
  numStr <- await
  liftIO $ putStrLn ("I received: " ++ numStr)

पाइप्स

पाइप await और yield दोनों कर सकते हैं।

type Pipe a b = Proxy () a () b

यह पाइप एक Int इंतजार करता है और इसे एक String परिवर्तित करता है:

intToStr :: Monad m => Pipe Int String m ()
intToStr = forever $ await >>= (yield . show)

RunEffect के साथ रनिंग पाइप

हम अपने Pipe को चलाने के लिए रन- runEffect का उपयोग करते हैं:

main :: IO ()
main = do
  runEffect $ naturalsUntil 10 >-> intToStr >-> fancyPrint

ध्यान दें कि runEffect लिए एक Effect आवश्यकता होती है, जो कि एक इनपुट या आउटपुट के साथ एक स्व-निहित Proxy :

runEffect :: Monad m => Effect m r -> m r
type Effect = Proxy X () () X

(जहाँ X खाली प्रकार है, जिसे Void भी कहा जाता है)।

पाइपों को जोड़ना

बड़े Pipe कार्यों की रचना करने के लिए Producer , Consumer और Pipe को जोड़ने के लिए >-> का उपयोग करें।

printNaturals :: MonadIO m => Effect m ()
printNaturals = naturalsUntil 10 >-> intToStr >-> fancyPrint

Producer , Consumer , Pipe , और Effect प्रकार सभी सामान्य Proxy प्रकार के संदर्भ में परिभाषित किए गए हैं। इसलिए >-> का उपयोग विभिन्न उद्देश्यों के लिए किया जा सकता है। बाएं तर्क द्वारा परिभाषित प्रकारों को सही तर्क द्वारा खपत प्रकार से मेल खाना चाहिए:

(>->) :: Monad m => Producer b m r -> Consumer b   m r -> Effect       m r
(>->) :: Monad m => Producer b m r -> Pipe     b c m r -> Producer   c m r
(>->) :: Monad m => Pipe   a b m r -> Consumer b   m r -> Consumer a   m r
(>->) :: Monad m => Pipe   a b m r -> Pipe     b c m r -> Pipe     a c m r

प्रॉक्सी मोनाड ट्रांसफार्मर

pipes का मुख्य डेटा प्रकार Proxy मोनाड ट्रांसफार्मर है। Pipe , Producer , Consumer और इतने पर Proxy संदर्भ में परिभाषित किया गया है।

चूंकि Proxy एक मोनड ट्रांसफ़ॉर्मर है, इसलिए Pipe परिभाषाएँ मोनैडिक स्क्रिप्ट्स का रूप लेती हैं जो मूल्यों का await और yield हैं, इसके अलावा बेस मोनड m से प्रभाव प्रदर्शन करते हैं।

पाइप्स और नेटवर्क संचार का मेल

पाइप क्लाइंट और सर्वर के बीच सरल बाइनरी संचार का समर्थन करता है

इस उदाहरण में:

  1. एक ग्राहक कनेक्ट करता है और एक FirstMessage भेजता है
  2. सर्वर DoSomething 0 को प्राप्त करता है और उत्तर देता है
  3. ग्राहक प्राप्त करता है और DoNothing जवाब DoNothing
  4. चरण 2 और 3 को अनिश्चित काल तक दोहराया जाता है

नेटवर्क पर एक्सचेंज किए गए कमांड डेटा प्रकार:

-- Command.hs
{-# LANGUAGE DeriveGeneric #-}
module Command where
import Data.Binary
import GHC.Generics (Generic)

data Command = FirstMessage
           | DoNothing
           | DoSomething Int
           deriving (Show,Generic)

instance Binary Command

यहां, सर्वर एक क्लाइंट को कनेक्ट करने के लिए इंतजार करता है:

module Server where

import Pipes 
import qualified Pipes.Binary as PipesBinary
import qualified Pipes.Network.TCP as PNT
import qualified Command as C
import qualified Pipes.Parse as PP
import qualified Pipes.Prelude as PipesPrelude

pageSize :: Int
pageSize = 4096

-- pure handler, to be used with PipesPrelude.map
pureHandler :: C.Command -> C.Command 
pureHandler c = c  -- answers the same command that we have receveid

-- impure handler, to be used with PipesPremude.mapM
sideffectHandler :: MonadIO m => C.Command -> m C.Command
sideffectHandler c = do
  liftIO $ putStrLn $ "received message = " ++ (show c)
  return $ C.DoSomething 0    
  -- whatever incoming command `c` from the client, answer DoSomething 0

main :: IO ()
main = PNT.serve (PNT.Host "127.0.0.1") "23456" $
  \(connectionSocket, remoteAddress) -> do
                 putStrLn $ "Remote connection from ip = " ++ (show remoteAddress)
                 _ <- runEffect $ do
                   let bytesReceiver = PNT.fromSocket connectionSocket pageSize
                   let commandDecoder = PP.parsed PipesBinary.decode bytesReceiver
                   commandDecoder >-> PipesPrelude.mapM sideffectHandler >-> for cat PipesBinary.encode >-> PNT.toSocket connectionSocket
                   -- if we want to use the pureHandler
                   --commandDecoder >-> PipesPrelude.map pureHandler >-> for cat PipesBinary.Encode >-> PNT.toSocket connectionSocket
                 return ()

ग्राहक इस प्रकार जोड़ता है:

module Client where

import Pipes
import qualified Pipes.Binary as PipesBinary
import qualified Pipes.Network.TCP as PNT
import qualified Pipes.Prelude as PipesPrelude
import qualified Pipes.Parse as PP
import qualified Command as C

pageSize :: Int
pageSize = 4096

-- pure handler, to be used with PipesPrelude.amp
pureHandler :: C.Command -> C.Command 
pureHandler c = c  -- answer the same command received from the server

-- inpure handler, to be used with PipesPremude.mapM
sideffectHandler :: MonadIO m => C.Command -> m C.Command
sideffectHandler c = do
  liftIO $ putStrLn $ "Received: " ++ (show c)
  return C.DoNothing  -- whatever is received from server, answer DoNothing

main :: IO ()
main = PNT.connect ("127.0.0.1") "23456" $
  \(connectionSocket, remoteAddress) -> do
    putStrLn $ "Connected to distant server ip = " ++ (show remoteAddress)
    sendFirstMessage connectionSocket
    _ <- runEffect $ do
      let bytesReceiver = PNT.fromSocket connectionSocket pageSize
      let commandDecoder = PP.parsed PipesBinary.decode bytesReceiver
      commandDecoder >-> PipesPrelude.mapM sideffectHandler >-> for cat PipesBinary.encode >-> PNT.toSocket connectionSocket
    return ()

sendFirstMessage :: PNT.Socket -> IO ()
sendFirstMessage s = do
  _ <- runEffect $ do
    let encodedProducer = PipesBinary.encode C.FirstMessage 
    encodedProducer >-> PNT.toSocket s  
  return ()


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow