【发布时间】:2011-07-19 10:26:51
【问题描述】:
我刚开始学习 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
谢谢, 抢
跟进
所有答案都很有帮助。下面的代码可以工作,但还没有按照建议使用字节串。一个后续问题: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
【问题讨论】:
-
感谢汤姆、以斯拉和丹。所有 3 个答案都有帮助。我会用这段代码玩一会儿,当我更好地理解事情时,将其中一个标记为答案。
标签: haskell io lazy-evaluation