2013-06-30 2 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

? 그것은 파이프에서 내부적으로 사용됩니까? – ajp

+4

@ajp이 동작은'pipes'에만 국한된 것이 아닙니다. 컴파일러는 여러분이 '영원히'호출하는 컨텍스트에서 사용할 모나드를 유추합니다. 컴파일러가 파이프가 아닌'Request ->'타입의 함수를 기대하고 있었기 때문에 우연히'forever go'를 사용했기 때문에 컴파일러는 당신이 의미하는 모나드가'Request ->'모나드이고'Server Request Response IO' 모나드. –