使用Pipes的简单程序挂起

ajp*_*ajp 7 haskell haskell-pipes

我有以下程序,在运行时不产生输出runhaskell Toy.hs,而是无限期挂起.根据我的理解,程序应该打印"hi"然后退出.我很感激有关如何调试此类问题的答案和/或建议.我正在使用Github的管道4.0.0(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
Run Code Online (Sandbox Code Playgroud)

Gab*_*lez 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
Run Code Online (Sandbox Code Playgroud)

您的原始版本挂起的原因是您foreverReadermonad(即((->) a)monad)中使用的而不是管道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
Run Code Online (Sandbox Code Playgroud)

foreverK可能是你想要的,因为它Serverpipes-3.3.0教程中介绍的s 相同.

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

>>> main
hi
>>>
Run Code Online (Sandbox Code Playgroud)

  • @ajp这种行为根本不是"管道"特有的.编译器推断出哪个monad在你称之为`forever`的上下文中使用.你不小心使用了`forever go`,编译器在那里期待一个类型为`Request - >`的函数,而不是一个管道,所以编译器推断你所说的monad是`Request - >`monad而不是`Server Request Response像你想要的IO` monad. (4认同)