首页 文章

使用Pipes的简单程序挂起

提问于
浏览
7

我有以下程序,使用 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 回答

  • 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
    

    您的原始版本挂起的原因是您在 Reader monad(即 ((->) a) monad)中使用 forever 而不是管道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 可能就是你想要的,因为它与 pipes-3.3.0 教程中引入的 Server 的成语相同 .

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

    >>> main
    hi
    >>>
    

相关问题