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"
答案 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 -> String
和toYear :: Int -> String
。你首先应该再考虑一下。