【问题标题】:How do I model time-based events in haskell?如何在 haskell 中为基于时间的事件建模?
【发布时间】:2026-01-18 02:30:02
【问题描述】:

我正在使用 haskell 构建一个队列多路复用器,部分是作为一种学习方式,部分是作为一些狡猾的 shell 脚本的替代品。

它的作用是定期连接到每个队列(我们使用的是 rabbitmq)来测量队列深度。如果主系统当前正在从一个队列消费并且该队列有消息,我们什么也不做。如果连接的队列是空的,我们切换到上面有最多消息的队列。如果所有队列都是空的,我们什么也不做。到目前为止一切顺利。

我还需要一个基于时间的切换,这样如果主应用已经连接到一个队列超过 1 小时并且队列是空的,那么即使所有其他队列都是空的,也要切换。

我在想我想要一些周期性地发出事件来触发下一个行为周期的东西,比如每分钟的“检查”事件和每小时的“时间切换”事件。

有没有一种惯用的方法在 haskell 中对基于时间的事件进行建模?

【问题讨论】:

  • 你想建模时间事件,还是你想要时间事件?
  • 听起来你可能更喜欢 Erlang 来完成这项任务......
  • Push-Pull FRP 描述了EventBehaviour 的有效实现(以及每个的形式语义)。

标签: haskell frp


【解决方案1】:

如果我理解正确的话,这听起来像是 Control.Concurrent 的工作。您将使用forkIO 来生成一个haskell 的轻量级线程来处理您的计时循环,并使用Chan 来接收计时信号。

import Control.Concurrent
import Control.Concurrent.Chan
import Control.Monad (forever)

main = do
  -- channel to receive messages from the timing thread
  chan <- newChan :: IO (Chan String)

  -- spawn a new thread to send periodic signals
  forkIO $ forever $ do
    writeChan chan "hi!"
    threadDelay $ 1 * 1000 * 1000 -- delay in microseconds

  -- in the main thread, listen for messages from the chan.
  forever $ readChan chan >>= print 

要对此进行扩展,您可以为您的活动创建一个 ADT,而不是将 Strings 写入 Chan,例如:

data Event = CheckEvent | SwitchEvent deriving Show

然后让你的监听线程根据事件类型做不同的事情。

【讨论】: