
Hi, all. Haskell's lazy IO causes below program to write back "ECHO result" to the user even if he doesn't give any input to the program. test1 :: IO () test1 = do l <- fmap lines getContents putStrLn "ECHO result" putStr $ unlines l If the client logic, that is the part for feeding data to this program and wait for the response, expect the server logic to respond only after all the client's request data are feed to the server logic, the behaviour could be problematic. I'm now writing simple web server, as you might guess, and my web server responds "HTTP/1.1" before any client's request are given. I'm using hGetContents and web server's logic is basically same with above code skeleton. How can I tell the program to respond data only after all the requests are feed? Any directions are welcomed. Thanks. Chul-Woong

Hi Chul-Woong, $ pwd | ./testprog ECHO result /tmp Your program works as you expect if you pipe some contents via STDIN. This is testprog.hs: main :: IO () main = do l <- fmap lines getContents putStrLn "ECHO result" putStr $ unlines l -Dan

I just realized I misread your question in a hurry and gave an irrelevant answer. Sorry about that.

Hi Chul-Woong,
Deepseq package can be used to make sure a list is actually fully
constructed before it's used.
import System.IO
import Control.DeepSeq
main :: IO ()
main = do
s <- getContents
s `deepseq` hClose stdin
putStrLn "ECHO result"
putStr s
Cheers
2014-07-24 9:07 GMT+03:00 양철웅
Hi, all.
Haskell's lazy IO causes below program to write back "ECHO result" to the user even if he doesn't give any input to the program.
test1 :: IO () test1 = do l <- fmap lines getContents putStrLn "ECHO result" putStr $ unlines l
If the client logic, that is the part for feeding data to this program and wait for the response, expect the server logic to respond only after all the client's request data are feed to the server logic, the behaviour could be problematic.
I'm now writing simple web server, as you might guess, and my web server responds "HTTP/1.1" before any client's request are given. I'm using hGetContents and web server's logic is basically same with above code skeleton.
How can I tell the program to respond data only after all the requests are feed? Any directions are welcomed. Thanks.
Chul-Woong
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Wow. DeepSeq is cool!
I 'deepseq'ed received request header and everything is OK.
Thanks Santtu!
2014-07-24 16:53 GMT+09:00 Santtu Keskinen
Hi Chul-Woong,
Deepseq package can be used to make sure a list is actually fully constructed before it's used.
import System.IO import Control.DeepSeq
main :: IO () main = do s <- getContents s `deepseq` hClose stdin putStrLn "ECHO result" putStr s
Cheers
2014-07-24 9:07 GMT+03:00 양철웅
: Hi, all.
Haskell's lazy IO causes below program to write back "ECHO result" to the user even if he doesn't give any input to the program.
test1 :: IO () test1 = do l <- fmap lines getContents putStrLn "ECHO result" putStr $ unlines l
If the client logic, that is the part for feeding data to this program and wait for the response, expect the server logic to respond only after all the client's request data are feed to the server logic, the behaviour could be problematic.
I'm now writing simple web server, as you might guess, and my web server responds "HTTP/1.1" before any client's request are given. I'm using hGetContents and web server's logic is basically same with above code skeleton.
How can I tell the program to respond data only after all the requests are feed? Any directions are welcomed. Thanks.
Chul-Woong
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

My biggest recommendation would be not to use lazy I/O. But excluding
that...
You just need to make sure that as much of the input is actually received
before sending a response. You do that by forcing evaluation of the thunk.
With lazy I/O, forcing evaluation ends up causing I/O to be performed,
which is what you want in this case. As an example, to make sure that at
least one character is received before continuing, you could use this
function:
getSomeContents = do
x <- getContents
case x of
[] -> return x
_:_ -> return x
Another possibility is to use *some* strict I/O. For example, you can get
the first character strictly and the rest lazily:
getSomeContents = do
c <- getChar
x <- getContents
return $ c : x
Something else you should think about is what data representation you want
to use. Everything we've done here using String, which is (1) inefficient,
since it's an unpacked representation, and (2) incorrect, since HTTP data
is really a series of bytes, not a series of unicode code points. But I'm
going on the assumption that this exercise is more to understand I/O
evaluation.
On Thu, Jul 24, 2014 at 9:07 AM, 양철웅
Hi, all.
Haskell's lazy IO causes below program to write back "ECHO result" to the user even if he doesn't give any input to the program.
test1 :: IO () test1 = do l <- fmap lines getContents putStrLn "ECHO result" putStr $ unlines l
If the client logic, that is the part for feeding data to this program and wait for the response, expect the server logic to respond only after all the client's request data are feed to the server logic, the behaviour could be problematic.
I'm now writing simple web server, as you might guess, and my web server responds "HTTP/1.1" before any client's request are given. I'm using hGetContents and web server's logic is basically same with above code skeleton.
How can I tell the program to respond data only after all the requests are feed? Any directions are welcomed. Thanks.
Chul-Woong
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Thank you, Michael, for kind explanation.
My first approach was calling the following sentinel function
before proceeding:
isValidReq req = (type req) /= ERROR && (length $ hdrs req) < 10000
The hdrs of (web) request are constructed lazily, so I should do length
call to
wait until full request are read.
With HTTP processing, I cannot figure out how to do with strict I/O.
Maybe complex parsing (parsec?) is required, I think.
So I changed the sentinel function using deepseq.
isVaidReq req = (hdrs req) `deepseq` (type req) /= ERROR
Regards,
Chul-Woong
2014-07-24 16:54 GMT+09:00 Michael Snoyman
My biggest recommendation would be not to use lazy I/O. But excluding that...
You just need to make sure that as much of the input is actually received before sending a response. You do that by forcing evaluation of the thunk. With lazy I/O, forcing evaluation ends up causing I/O to be performed, which is what you want in this case. As an example, to make sure that at least one character is received before continuing, you could use this function:
getSomeContents = do x <- getContents case x of [] -> return x _:_ -> return x
Another possibility is to use *some* strict I/O. For example, you can get the first character strictly and the rest lazily:
getSomeContents = do c <- getChar x <- getContents return $ c : x
Something else you should think about is what data representation you want to use. Everything we've done here using String, which is (1) inefficient, since it's an unpacked representation, and (2) incorrect, since HTTP data is really a series of bytes, not a series of unicode code points. But I'm going on the assumption that this exercise is more to understand I/O evaluation.
On Thu, Jul 24, 2014 at 9:07 AM, 양철웅
wrote: Hi, all.
Haskell's lazy IO causes below program to write back "ECHO result" to the user even if he doesn't give any input to the program.
test1 :: IO () test1 = do l <- fmap lines getContents putStrLn "ECHO result" putStr $ unlines l
If the client logic, that is the part for feeding data to this program and wait for the response, expect the server logic to respond only after all the client's request data are feed to the server logic, the behaviour could be problematic.
I'm now writing simple web server, as you might guess, and my web server responds "HTTP/1.1" before any client's request are given. I'm using hGetContents and web server's logic is basically same with above code skeleton.
How can I tell the program to respond data only after all the requests are feed? Any directions are welcomed. Thanks.
Chul-Woong
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (5)
-
Chul-Woong Yang
-
Dan Serban
-
Michael Snoyman
-
Santtu Keskinen
-
양철웅