KnowledgeHub
Questions
Tags
Users
Search
Alex Rivera
|
Logout
Edit Question
Title
Body
I just started learning Haskell. Below is some code written in an imperative style that implements a simple server -- it prints out the HTTP request headers. Besides the fact that I need to rethink it in Haskell, to work with lazy lists and higher order functions, I'd like to see clearly why it does not do what I intended. It is always one behind -- I hit it with a request, nothing happens, hit it again, it prints the first request, hit it the 3rd time, it prints the 2nd request, etc. Why is that? And what is a minimal change to this code that would cause it to print right when the request came in? 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 thanks, Rob Followup All the answers were helpful. The code below works, but does not use bytestrings, as suggested, yet. A followup question: can ioTakeWhile be replaced by using some functions from the standard libraries, maybe in 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
Tags (comma-separated)
Save Edits
Cancel