Como faço para sair de um loop em Haskell?

oversão atual do tutorial Pipes, usa as duas funções a seguir em um dos exemplos:

 stdout :: () -> Consumer String IO r
 stdout () = forever $ do
     str <- request ()
     lift $ putStrLn str

 stdin :: () -> Producer String IO ()
 stdin () = loop
   where
     loop = do
         eof <- lift $ IO.hIsEOF IO.stdin
         unless eof $ do
             str <- lift getLine
             respond str
             loop

Como é mentinoed no próprio tutorial, P.stdin é um pouco mais complicado devido à necessidade de verificar o final da entrada.

Existe alguma maneira legal de reescrever P.stdin para não precisar de um loop recursivo de cauda manual e usar combinadores de fluxo de controle de ordem mais alta como o P.stdout? Em uma linguagem imperativa, eu usaria um loop while estruturado ou uma instrução break para fazer a mesma coisa:

while(not IO.isEOF(IO.stdin) ){
    str <- getLine()
    respond(str)
}

forever(){
    if(IO.isEOF(IO.stdin) ){ break }
    str <- getLine()
    respond(str)
}

questionAnswers(4)

yourAnswerToTheQuestion