模式守卫并允许

时间:2017-02-13 16:03:29

标签: haskell

在完成项目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 ()

导致此行为的原因是什么?

1 个答案:

答案 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 ]