【问题标题】:Refactor an IO recursive loop into a monad folding in Haskell在 Haskell 中将 IO 递归循环重构为 monad 折叠
【发布时间】:2015-06-19 05:48:25
【问题描述】:

我写了一个tcp服务器,这是我的主循环方法:

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

(注意:handleConn :: Socket -&gt; IO () 是我的程序特有的函数。)

我想将其重构为更 monadic 的方式,这是我的尝试:

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

但这会使程序在我开始通过套接字发送数据时立即崩溃。

这是我的问题:为什么?解决办法是什么?

【问题讨论】:

  • 你为什么用foldl而不是foldM_
  • 你所说的“更单子”是什么意思?
  • 我认为 foldl1 是导致崩溃的罪魁祸首 - 你不能有效地将折叠放在无限列表上,它会无限循环或引发异常,并且可能会耗尽内存。

标签: sockets haskell network-programming io-monad


【解决方案1】:

永远一遍又一遍地重复相同动作的惯用方式是forever

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

【讨论】:

    【解决方案2】:

    我不知道你所说的“更多单子”是什么意思,但你的函数可以这样写:

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

    【讨论】:

      猜你喜欢
      • 2011-03-03
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-01
      • 2020-04-04
      相关资源
      最近更新 更多