询问是否存在定时重复执行功能及Haskell库提供repeatEvery函数
有没有Haskell库提供「每隔指定时间重复执行动作」的功能?
我在优化自己试验的Haskell通知服务器时,手写了下面这段代码:
import Control.Concurrent (threadDelay) import Control.Monad (forever) repeatEvery :: Int -> IO () -> IO () repeatEvery time action = forever $ action >> threadDelay time
使用方式如下:
repeatEvery oneSec $ do stuff
我想知道有没有现成的Haskell库暴露了类似repeatEvery的函数——我在Hoogle上搜索类型签名a -> f b -> f b没找到相关结果,会不会是这类函数的类型签名和我写的不一样?
相关库中的实现
1. async库的repeatedly
async库提供了repeatedly函数,它会无限重复执行传入的IO动作,但没有直接的间隔时间参数。你可以把动作和threadDelay打包后传入,间接实现定时重复:
import Control.Concurrent (threadDelay) import Control.Concurrent.Async (repeatedly) repeatEvery time action = repeatedly $ action >> threadDelay time
它的类型签名是:
repeatedly :: IO a -> IO b
2. schedule库
schedule库专注于定时任务调度,支持固定间隔、Cron表达式等多种调度规则。其中scheduleAction可以实现你的需求:
import qualified Schedule as S main = do let action = putStrLn "执行定时任务" -- 每隔1秒执行一次 S.scheduleAction (S.everySeconds 1) action -- 阻塞等待调度任务执行 S.waitForSchedule
3. time-manager库
这个库的repeatAction直接支持指定间隔时间,类型签名更贴合你的需求:
repeatAction :: NominalDiffTime -> IO () -> IO ()
使用时需要用NominalDiffTime类型定义间隔(以秒为单位的浮点数):
import Data.Time.Clock (secondsToNominalDiffTime) import Time.Manager (repeatAction, withTimeManager) main = withTimeManager $ \tm -> do let oneSec = secondsToNominalDiffTime 1 repeatAction oneSec (putStrLn "每隔1秒执行一次")
4. 基于base库的优化版本
你自己手写的实现已经足够简洁,如果不想引入额外依赖,可以优化时间单位的可读性,用标准库的时间类型替代原始的微秒整数:
import Control.Concurrent (threadDelay) import Control.Monad (forever) import Data.Time.Clock (NominalDiffTime, diffTimeToPicoseconds) repeatEvery :: NominalDiffTime -> IO () -> IO () repeatEvery delay action = forever $ do action -- 将NominalDiffTime转换为微秒,适配threadDelay的参数要求 threadDelay $ fromIntegral $ diffTimeToPicoseconds delay `div` 1000000
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

