使用Pipes的简单程序挂起

时间:2013-06-30 01:06:24

标签: haskell haskell-pipes

我有以下程序,当使用runhaskell Toy.hs运行时不会产生输出,而是无限期挂起。根据我的理解,程序应该打印“hi”然后退出。我很感激有关如何调试此类问题的答案和/或建议。我正在使用Github(github.com/Gabriel439/Haskell-Pipes-Library)的Pipes 4.0.0。

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

1 个答案:

答案 0 :(得分:9)

您需要使用foreverK代替forever,如下所示:

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

原始版本挂起的原因是您在forever monad(即Reader monad)中使用((->) a)而不是管道monad。在此monad中,forever相当于

-- 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可能就是您想要的,因为它与Server教程中引入的pipes-3.3.0成语相同。

此更改修复了现在正常完成的程序:

>>> main
hi
>>>