Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple program using Pipes hangs

I have the following program, which produces no output when run with runhaskell Toy.hs, and instead hangs indefinitely. By my understanding, the program should print "hi" and then exit. I would appreciate an answer and/or advice about how to debug such an issue. I'm using Pipes 4.0.0 off of github (github.com/Gabriel439/Haskell-Pipes-Library).

module Toy where

import Pipes
import Control.Monad.State

type Request = String
type Response = String

serveChoice :: Request -> Server Request Response IO ()
serveChoice = forever go
  where go req = do
        lift $ putStrLn req
        respond req

run :: Monad m => () -> Client Request Response (StateT Int m) ()
run () = do
    request "hi"
    return ()

main :: IO ()
main = evalStateT (runEffect $ hoist lift . serveChoice >-> run $ ()) 0
like image 972
ajp Avatar asked Jun 30 '13 01:06

ajp


People also ask

How does pipe () work?

Pipe is used to combine two or more commands, and in this, the output of one command acts as input to another command, and this command's output may act as input to the next command and so on. It can also be visualized as a temporary connection between two or more commands/ programs/ processes.

Is pipe () a system call?

pipe() is a system call that facilitates inter-process communication. It opens a pipe, which is an area of main memory that is treated as a "virtual file". The pipe can be used by the creating process, as well as all its child processes, for reading and writing.

What is pipes in C programming?

A pipe is a system call that creates a unidirectional communication link between two file descriptors. The pipe system call is called with a pointer to an array of two integers. Upon return, the first element of the array contains the file descriptor that corresponds to the output of the pipe (stuff to be read).

What is pipe system call in Linux?

pipe() is a Linux system function. The pipe() system function is used to open file descriptors, which are used to communicate between different Linux processes. In short, the pipe() function is used for inter-process communication in Linux.


1 Answers

You need to use foreverK instead of forever, like this:

module Toy where

import Pipes
import Pipes.Prelude (foreverK)
import Control.Monad.State

type Request = String
type Response = String

serveChoice :: Request -> Server Request Response IO ()
serveChoice = foreverK go
  where go req = do
        lift $ putStrLn req
        respond req

run :: Monad m => () -> Client Request Response (StateT Int m) ()
run () = do
    request "hi"
    return ()

main :: IO ()
main = evalStateT (runEffect $ hoist lift . serveChoice >-> run $ ()) 0

The reason your original version hangs is that you used forever in the Reader monad (i.e. the ((->) a) monad) and not the pipe monad. Within this monad, forever is equivalent to :

-- i.e.        m b  ->     m c
forever :: (a -> b) -> (a -> c)
forever m = m >> forever m
          = m >>= \_ -> forever m
          = \a -> (\_ -> forever m) (m a) a
          = \a -> forever m a
          = forever m

foreverK is probably what you wanted, since it is the same idiom for Servers introduced in the pipes-3.3.0 tutorial.

This change fixes the program which now completes normally:

>>> main
hi
>>>
like image 130
Gabriella Gonzalez Avatar answered Sep 27 '22 18:09

Gabriella Gonzalez