Haskell函数将日期的一部分作为字符串

时间:2011-04-06 22:04:27

标签: datetime haskell io monads

我有一个关于约会的初学者问题和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中的日期。

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

提前感谢您的帮助!

4 个答案:

答案 0 :(得分:10)

如果你想返回一个表示当前时间的字符串,它将成为IO monad,因为当前时间的值总是在变化!

您可以做的是在IO monad中返回一个String:

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

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

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

答案 1 :(得分:5)

如果你真的想要那种纯函数,那么你需要明确地将时间作为参数传递。

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可能需要几个小时。

答案 2 :(得分:2)

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

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

祝学习Haskell好运!

答案 3 :(得分:1)

你不能只获得一个String,它必须是IO String。这是因为getCurrMonth不是纯函数,它在不同的时间返回不同的值,因此它必须在IO中。