在Haskell中调试时打印时间戳

时间:2017-01-14 21:31:27

标签: haskell io bind

我还在学习Haskell并调试一些函数,并且通常有一个时间戳函数来了解某些操作何时开始和停止:

doSomeAction :: String -> IO ()
doSomeAction arg1 = do
  putStrLn =<< makeTime
  theThingthatTakesAwhile arg1
  putStrLn =<< makeTime
  where
    makeTime = (formatTime defaultTimeLocale "%Y%m%d%H%M%S") <$> getZonedTime

我的=<<where子句是否包含<$>getZonedTime周围的IO进行交互的合理方式?

λ> :t getZonedTime
getZonedTime :: IO ZonedTime

或者这是误导我或读者还是非惯用的?

输出是:

20170114152312
Doing some long function....
20170114152336

这正是我想看到的 - 它告诉我我需要什么。 putStrLn =<< something获得这种效果似乎很奇怪。

2 个答案:

答案 0 :(得分:3)

你的代码非常好。任何熟悉Haskell的程序员都应该很快理解它。

但是,按照我自己的风格,我倾向于在Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32 块中更喜欢let

do

或可能是

的一些变体
doSomeAction :: String -> IO ()
doSomeAction arg1 = do
  let makeTime = formatTime defaultTimeLocale "%Y%m%d%H%M%S" <$> getZonedTime
  putStrLn =<< makeTime
  theThingthatTakesAwhile arg1
  putStrLn =<< makeTime

但同样,这只是个人偏好的问题。

答案 1 :(得分:1)

如果使用某些日志记录库,则可以做得更好。例如hslogger。它可以打印带有时间戳的消息。您可以在此问题下查看使用示例:hslogger & Duplicate Log Lines

UPD: 记录时间戳的示例

以下是记录初始化的模块的完整示例:

import           Control.Concurrent        (threadDelay)
import           System.IO                 (stdout)
import           System.Log.Formatter      (simpleLogFormatter)
import           System.Log.Handler        (setFormatter)
import           System.Log.Handler.Simple (streamHandler)
import           System.Log.Logger         (Priority (DEBUG), debugM, rootLoggerName,
                                            setHandlers, setLevel, updateGlobalLogger)

initLogging :: IO ()
initLogging = do
    stdOutHandler <- streamHandler stdout DEBUG >>= \lh -> return $
            setFormatter lh (simpleLogFormatter "[$loggername:$time] $msg")
    updateGlobalLogger rootLoggerName (setLevel DEBUG . setHandlers [stdOutHandler])

doSomeAction :: String -> IO ()
doSomeAction arg1 = do
    debugM "someAction" "before long thing"
    theThingThatTakesAWhile arg1
    debugM "someAction" "after long thing"

theThingThatTakesAWhile :: String -> IO ()
theThingThatTakesAWhile arg = threadDelay (3 * 10^(6 :: Int)) >> putStrLn arg

main :: IO ()
main = do
    initLogging
    doSomeAction "some long action" 

输出是:

[someAction:2017-01-16 17:19:49 MSK] before long thing
some long action
[someAction:2017-01-16 17:19:52 MSK] after long thing

如果您希望时间打印为时间戳(仅秒),则可以使用tfLogFormatter功能指定消息的确切格式。