一年中的第几天
【题目】给定年月日,求这一天是该年份中的第几天。元旦作为该年的第一天。
这个问题相对容易。
关键是算出 2 月份有多少天。
把每个月的天数放在数组中,然后累加已过去的月份的天数,再加上不足一个月的天数。
haskell 代码如下:
di_ji :: (Int,Int,Int) -> Int
di_ji (y,m,d) =
let run_nian = y `mod` 4 == 0 && y `mod` 100 /= 0 || y `mod` 400 == 0
mon = [31,if run_nian then 29 else 28
,31,30,31,30,31,31,30,31,30,31]
in sum (take (m-1) mon) + d
main = do
s <- getLine
let [y,m,d] = words s
print $ di_ji (read y, read m, read d)
这里可以看到 haskell 作为纯函数式的语言,一切都是表达式。表达式必须返回一个值。
if … then …else … 就是一个表达式,无论如何,它都会吐出一个同样类型的值。
let … in … 也是一个表达式,它的值就是 in 表达式的返回值。
read 是一个多态的函数。它可能返回各种类型的值。在这里,编译器看到了 di_ji 的参数是 Int
所以它选择了返回 Int 的那个read 实现版本。
实际上 do 语句块也是一个表达式。它是 Monad IO 函数的串联式的一种语法糖。
看起来好像是一条条的命令语句,实则只是一个
表达式。
总之,haskell 中只有函数,表达式,没有命令,
无法赋值,没有循环,break, goto 等所谓控制程序流程的东西都没有!!
你无权知道表达式求值的先后顺序。
你只是定义表达式间的信赖关系。
你只能问某个表达式的结果是多少?至于如何设计计算路径,全是编译器的事。
哪个表达式什么时候求值,甚至是到底要不要求值,都是编译器的责任。