我有一个关于约会的初学者问题和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中的日期。
那么,有没有办法编写这样的函数?
提前感谢您的帮助!
答案 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中。