Я только начал изучать Haskell. Ниже приведен код, написанный в императивном стиле, который реализует простой сервер - он печатает заголовки HTTP-запросов. Помимо того, что мне нужно переосмыслить его в Haskell, работать с ленивыми списками и функциями более высокого порядка, я хотел бы четко понять, почему он не делает то, что я намеревался. Это всегда одно - я ударил его запросом, ничего не случилось, снова ударил его, он распечатывает первый запрос, ударяет его в третий раз, печатает второй запрос и т.д. Почему? И каково минимальное изменение этого кода, которое могло бы привести его к печати сразу после запроса?
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
спасибо, Rob
Followup
Все ответы были полезными. Приведенный ниже код работает, но пока не использует bytestrings, как это было предложено. Следующий вопрос: можно ли заменить ioTakeWhile
на некоторые функции из стандартных библиотек, возможно, в 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