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