2013-06-30 4 views
7

私はrunhaskell Toy.hsで実行すると出力を生成せず、代わりに無期限にハングアップする次のプログラムを持っています。私の理解では、プログラムは "hi"を印刷してから終了する必要があります。私はそのような問題をデバッグする方法についての答えおよび/または助言に感謝します。私はgithub(github.com/Gabriel439/Haskell-Pipes-Library)からパイプ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 

答えて

9

あなたはこのように、foreverの代わりにforeverKを使用する必要があります。

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 

あなたの元のバージョンがハング理由は、あなたが(すなわち((->) a)モナド)とないReaderモナドでforeverを使用したことですパイプモナド。このモナドの中で、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 
>>> 
+0

はどこリーダーモナドは、映像に入って来るのでしょうか?それはPipesの内部で使用されていますか? – ajp

+4

@ajpこの動作は 'pipes'に固有のものではありません。コンパイラは、あなたが 'forever'を呼び出すコンテキストによってどのモナドを使うかを推論します。コンパイラはパイプではなく 'Request - >'型の関数を期待していたので、誤って 'forever go'を使用していたので、' Request - > 'モナドであり、' Server Request Responseあなたが意図したような「IO」モナド。 –

関連する問題