【问题标题】:Haskell function to get part of date as stringHaskell函数将日期的一部分作为字符串
【发布时间】:2011-07-31 05:17:16
【问题描述】:

我有一个关于 Haskell 中日期和 String 的初学者问题。

我需要在 Haskell 中以 String 的形式获取部分日期(年、月或日)。我发现,如果我在 GHCi 中写以下两行

Prelude> now <- getCurrentTime
Prelude> let mon = formatTime defaultTimeLocale "%B" now

那么mon 的类型是String。但是,我无法将其放入函数中。例如,我尝试了以下方法:

getCurrMonth = do
    now <- getCurrentTime
    putStrLn (formatTime defaultTimeLocale "%B" now)

但这返回类型IO (),我需要String(也不是IO String,只有String)。

我知道do 语句创建了一个我不想要的 monad,但我无法在 Haskell 中找到任何其他获取日期的解决方案。

那么,有没有办法写出这样的函数呢?

提前感谢您的帮助!

【问题讨论】:

    标签: datetime haskell io monads


    【解决方案1】:

    如果你想返回一个代表当前时间的String,它必须在IO monad中,因为当前时间的值总是在变化的!

    你可以做的是在 IO monad 中返回一个字符串:

    > getCurrMonth :: IO String
    > getCurrMonth = do
    >    now <- getCurrentTime
    >    return (formatTime defaultTimeLocale "%B" now)
    

    然后,从您的顶层(例如在 main 中),您可以传递字符串:

    > main = do
    >     s <- getCurrMonth
    >     ... do something with s ...
    

    【讨论】:

      【解决方案2】:

      如果你真的想要一个纯函数,那么你需要将时间显式地作为参数传递。

      import System.Locale (defaultTimeLocale)
      import System.Time (formatCalendarTime, toUTCTime, getClockTime, ClockTime)
      
      main = do now <- getClockTime
                putStrLn $ getMonthString now
      
      getMonthString :: ClockTime -> String
      getMonthString = formatCalendarTime defaultTimeLocale "%B" . toUTCTime
      

      注意getMonthString 可以是纯的,因为 IO 操作 getClockTime 在其他地方执行。

      我使用了old-time 函数,因为我是testing it out on codepad,它显然没有更新的时间包。 :( 我是旧时间函​​数的新手,所以这可能会关闭几个小时,因为它使用 toUTCTime

      【讨论】:

      • +1 用于展示如何使“不纯的部分”尽可能小。
      【解决方案3】:

      正如 Don 所说,在这种情况下无法避免使用 monad。请记住,Haskell 是一种纯函数式语言,因此在给定特定输入的情况下,函数必须始终返回相同的输出。 Haskell.org 提供了很好的解释和介绍here,当然值得一看。您也可能会从 this one 之类的 monad 介绍或 this one 之类的 Haskell I/O 教程中受益。当然,您可以在网上找到更多资源。 Monad 最初可能令人生畏,但它们实际上并不像最初看起来那么困难。

      哦,我强烈建议不要使用unsafePerformIO。它的名称中有“不安全”一词是有充分理由的,而且它绝对不是为这种情况而创建的。使用它只会导致坏习惯和问题。

      祝你学习 Haskell 好运!

      【讨论】:

      • 非常感谢您的链接,我终于可以更好地理解单子了。我们在学校学习 Haskell 的方式非常混乱。
      【解决方案4】:

      你不能只得到一个字符串,它必须是 IO 字符串。这是因为getCurrMonth不是纯函数,它在不同的时间返回不同的值,所以必须在IO中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-08
        • 2019-02-20
        • 2023-04-05
        • 2012-01-06
        • 2020-03-19
        相关资源
        最近更新 更多