Refactor an IO recursive loop into a monad folding in Haskell

236 Views Asked by At

I writing a tcp server, and here's my main loop method:

serverLoop :: Socket -> IO ()
serverLoop sock = do
    (conn, _) <- accept sock
    forkIO $ handleConn conn
    serverLoop sock

(Note: handleConn :: Socket -> IO () is a function specific to my program.)

I would like to refactor that into a more monadic way, here's my tentative:

serverLoop :: Socket -> IO ()
serverLoop sock = foldl1 (>>) $ map go $ repeat sock
     where go sock = (accept sock) >>= (forkIO . handleConn . fst) >> return ()

But this makes the program crash as soon as I start sending data through the socket.

Here are my questions: why? what's the fix for that?

2

There are 2 best solutions below

0
On BEST ANSWER

The idiomatic way to repeat the same action over and over again forever is forever

serverLoop :: Socket -> IO ()
serverLoop sock = forever $ do
    (conn, _) <- accept sock
    forkIO $ handleConn conn
0
On

I don't know what you mean by "more monadic", but your function can be written this way:

serverLoop :: Socket -> IO ()
serverLoop sock = forever (accept sock >>= forkIO . handleConn . fst)