我有一个关于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
语句创建了一个单子,这是我不想要的,但我一直无法找到在Haskell中获取日期的任何其他解决方案。
那么,有没有办法写出这样一个函数呢?
提前感谢您的帮助!
如果你想返回一个表示当前时间的字符串,它将在IO单子中有,因为当前时间的值总是在变化!
你能做的就是在IO单子中返回一个String:
> getCurrMonth :: IO String
> getCurrMonth = do
> now <- getCurrentTime
> return (formatTime defaultTimeLocale "%B" now)
然后,从你的顶层(例如在main中),你可以传递字符串:
> main = do
> s <- getCurrMonth
> ... do something with s ...
如果你真的想要一个这样的纯函数,那么你需要显式地将时间作为参数传入。
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
是在其他地方执行的。
我使用了旧的函数,因为我是在codepad上测试它的,它显然没有较新的时间包。:(我对旧的时间函数不熟悉,所以这可能会关闭几个小时,因为它使用toUTCTime
.
正如Don所说,在这种情况下无法避免使用单子。请记住,Haskell是一种纯函数式语言,因此给定特定的输入,函数必须始终返回相同的输出。Haskell.org在这里提供了很好的解释和介绍,当然值得一看。您也可能受益于monad的介绍,如本文或Haskell I/O教程,如本文。当然,你可以在网上找到更多的资源。单子一开始可能会让人望而生畏,但它们并不像一开始看起来那么难。
哦,我强烈建议不要使用unsafePerformIO
。它的名字中有"不安全"这个词是有充分理由的,而且它绝对不是为这种情况而创建的。使用它只会导致坏习惯和问题。
祝你学习Haskell好运!
你不能只得到一个String,它必须是IO String。这是因为getCurrMonth不是一个纯粹的函数,它在不同的时间返回不同的值,所以它必须在IO中。