Haskell holgazanería: ¿cómo forzo que el IO suceda antes?

Acabo de empezar a aprender Haskell. A continuación se muestra un código escrito en un estilo imperativo que implementa un servidor simple: imprime los encabezados de solicitud HTTP. Además del hecho de que necesito repensarlo en Haskell, para trabajar con listas perezosas y funciones de orden superior, me gustaría ver claramente por qué no hace lo que pretendía. Siempre está uno detrás: lo golpeo con una solicitud, no pasa nada, lo golpeo de nuevo, imprime la primera solicitud, lo golpeo la tercera vez, imprime la segunda solicitud, etc. ¿Y cuál es un cambio mínimo en este código que podría hacer que se imprima justo cuando llegó la solicitud?

import Network
import System.IO
import Network.HTTP.Headers

acceptLoop :: Socket -> IO ()
acceptLoop s = do
  (handle, hostname, _) <- accept s
  putStrLn ("Accepted connection from " ++ hostname)
  text <- hGetContents handle
  let lns = lines text
      hds = tail lns
  print $ parseHeaders hds
  hClose handle
  acceptLoop s


main :: IO ()
main = do
  s <- listenOn (PortNumber 8080)
  acceptLoop s

gracias, Rob

Segui

Todas las respuestas fueron útiles. El siguiente código funciona, pero aún no utiliza cadenas de bytes, como se sugiere. Una pregunta de seguimiento: canioTakeWhile ser reemplazado utilizando algunas funciones de las bibliotecas estándar, tal vez en Control.Monad?

ioTakeWhile :: (a -> Bool) -> [IO a] -> IO [a]
ioTakeWhile pred actions = do
  x <- head actions
  if pred x
    then (ioTakeWhile pred (tail actions)) >>= \xs -> return (x:xs)
    else return []

acceptLoop :: Socket -> IO ()
acceptLoop s = do
  (handle, hostname, _) <- accept s
  putStrLn ("Accepted connection from " ++ hostname)
  let lineActions = repeat (hGetLine handle)
  lines <- ioTakeWhile (/= "\r") lineActions
  print lines
  hClose handle

Respuestas a la pregunta(3)

Su respuesta a la pregunta