日期 - 哈斯克尔

时间:2018-06-03 10:28:24

标签: haskell

module Date where

type Date = (Int,Int,Int)

showDate :: Date -> String
showDate (d,m,y) = undefined --TODO

输入showDate (1,1,2001)应输出"1st January, 2001"

任何人都知道我怎么能这样做?我有一个想法,只是不确定如何解决它。

更新

toMonth :: Int -> String
toMonth x = case x of
1 -> "January"
2 -> "February"
3 -> "March"
4 -> "April"
5 -> "May"
6 -> "June"
7 -> "July"
8 -> "August"
9 -> "September"
10 -> "October"
11 -> "November"
12 -> "December"
otherwise -> "error"

1 个答案:

答案 0 :(得分:2)

首先,请务必注意缩进。

toMonth x = case x of
             1 -> "January"
             2 -> "February"
             3 -> "March"
             ...

(你不需要那么多的缩进,toMonth右边只有一个空格也可以;但我喜欢将case case子句缩进到case关键字本身以外的一个。)

不使用case构造通常更简单,只需要几个函数子句,比如

toMonth 1 = "January"
toMonth 2 = "February"
toMonth 3 = "March"
...

这是一个品味问题。

对于错误情况:您不能在此处使用otherwise,因为您正在使用模式匹配otherwise只是True的简写,因此可以在布尔条件中使用,即在 guards 中,但在这里您需要字符串模式。无所不包的模式是_,而不是otherwise。另外,不要将包含error字符串作为结果。这在实践中非常混乱。相反,请使用标准error函数,该函数会使程序崩溃,并提供有关出错的有用信息。 (这是一个例外,必要时可以由主程序捕获和处理。)

toMonth 12 = "December"
toMonth _ = error "Month number must be in range 1-12."

另一种不那么详细(虽然也不那么健壮)的方法是从单个字符串中取出月份名称,例如

toMonth n
  | n>0 && n<13  = names !! (n-1)
  | otherwise    = error "Month number must be in range 1-12."
 where names = words $ "January February March April May June July"
                    ++ " August September October November December"

这在这里并不值得,但当你不仅有12个案例而是数百个案例时,这个成语更加明智。然后,您还应该将名称存储在列表中,而不是Vector,以便更快地查找。

因此,一旦您编写并测试了toMonth,就可以在showDate中使用它,如下所示:

showDate (d,m,y) = toDayNumber d ++ " " ++ toMonth m ++ ", " ++ toYear y

您仍然需要实施toDayNumber :: Int -> StringtoYear :: Int -> String。你首先应该再考虑一下。