2013-06-30 12 views
7

Ho il seguente programma, che non produce output quando viene eseguito con runhaskell Toy.hs e si blocca invece indefinitamente. Secondo la mia comprensione, il programma dovrebbe stampare "ciao" e quindi uscire. Gradirei una risposta e/o un consiglio su come eseguire il debug di questo problema. Sto usando Pipes 4.0.0 su github (github.com/Gabriel439/Haskell-Pipes-Library).Il programma semplice che utilizza i tubi si blocca

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 

risposta

9

è necessario utilizzare foreverK invece di forever, in questo modo:

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 

La ragione per la versione originale si blocca è che si è utilizzato forever nel Reader Monade (cioè il ((->) a) Monade) e non il pipe monad. All'interno di questa monade, forever è equivalente a :

-- 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 è probabilmente quello che si voleva, dal momento che è lo stesso linguaggio per Server s introdotti nel pipes-3.3.0 tutorial.

Questo cambiamento fissa il programma che ora completa normalmente:

>>> main 
hi 
>>> 
+0

Da dove viene la monade Reader entrano in gioco, come non ho mai invocato esplicitamente? Viene utilizzato internamente in pipe? – ajp

+4

@ajp Questo comportamento non è affatto specifico di 'pipe'. Il compilatore deduce quale monade usare dal contesto in cui si chiama 'per sempre'. Hai usato per sbaglio 'per sempre go' dove il compilatore si aspettava una funzione di tipo' Request -> ', non una pipe, quindi il compilatore deduceva che la monade che intendevi era la' Request -> 'monad e non la' Request Request Response IO' monad come volevi. –

Problemi correlati