在完成项目euler的第一对练习时,我对haskell处理失败的方式感到惊讶。 我打算做相同的事情:
sundays = length $ do
year <- [1901..2000]
month <- [1..12]
(_, _, 7) <- return . toWeekDate $ fromGregorian year month 1
return ()
即,检查某个时间段内某月的第一天是星期日的频率。这有效,并且使用案例绑定也可以。看起来它应该做同样事情的let绑定总是通过,但是:
sundays = length $ do
year <- [1901..2000]
month <- [1..12]
let (_, _, 7) = toWeekDate $ fromGregorian year month 1
return ()
导致此行为的原因是什么?
答案 0 :(得分:6)
永远不会评估第二个示例中的let
绑定,因为它的值从未使用过。它与写作相同:
sundays = length $ do
year <- [1901..2000]
month <- [1..12]
return ()
如果您想扩展第二个示例,我建议您使用Control.Monad
中的guard
,这将有效地按预期过滤结果:
sundays2 = length $ do
year <- [1901..2000]
month <- [1..12]
let (_, _, day) = toWeekDate $ fromGregorian year month 1
guard $ day == 7
return ()
guard
是列表理解中幕后使用的内容。您上面的代码可以用以下列表理解形式编写:
sundays3 = length $ [ () | year <- [1901..2000]
, month <- [1..12]
, let (_, _, day) = toWeekDate $ fromGregorian year month 1
, day == 7 ]