开发者

Haskell function to get part of date as string

开发者 https://www.devze.com 2023-02-23 03:17 出处:网络
I have a beginner question about dates and String in Haskell. I need to get part of date (year, month or day) as String in Haskell. I found out, that if I write the following two lines in GHCi

I have a beginner question about dates and String in Haskell.

I need to get part of date (year, month or day) as String in Haskell. I found out, that if I write the following two lines in GHCi

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

then mon is of type String. However, I am unable to put this in a function. I tried for instance the following:

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

But this returns type IO () and I need String (also not IO String, only String).

I understand that do statement creates a monad, which I don't want, but I have been unable to find any other solution for getting date in Haskell.

So, is 开发者_如何学运维there any way to write a function like this?

Thanks in advance for any help!


If you want to return a String representing the current time, it will have to be in the IO monad, as the value of the current time is always changing!

What you can do is to return a String in the IO monad:

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

then, from your top level (e.g. in main), you can pass the String around:

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


If you really want a pure function of that sort, then you need to pass in the time explicitly as a parameter.

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

Notice how getMonthString can be pure since the IO action getClockTime is performed elsewhere.

I used the old-time functions, because I was testing it out on codepad, which apparently doesn't have the newer time package. :( I'm new to the old time functions so this might be off a couple hours since it uses toUTCTime.


As Don said, there's no way to avoid using monads in this situation. Remember that Haskell is a pure functional language, and therefore a function must always return the same output given a particular input. Haskell.org provides a great explanation and introduction here that is certainly worth looking at. You'd also probably benefit from monad introduction like this one or a Haskell I/O tutorial like this one. Of course there are tons more resources online you can find. Monads can initially be daunting, but they're really not as difficult as they seem at first.

Oh, and I strongly advise against using unsafePerformIO. There's a very good reason it has the word "unsafe" in the name, and it was definitely not created for situations like this. Using it will only lead to bad habits and problems down the line.

Good luck learning Haskell!


You can't get just a String, it has to be IO String. This is because getCurrMonth is not a pure function, it returns different values at different times, so it has to be in IO.

0

精彩评论

暂无评论...
验证码 换一张
取 消