我有一个函数,输出一个月的天数,需要改变守卫和使用模式匹配。`
daysInMonth :: Int -> Int
daysInMonth m
| m == 4 || m == 6 || m == 9 || m == 11 = 30
| m == 2 = 28
| m > 12 || m < 0 = error "Month does not exist"
| m == m = 31
“我能把第4、6、9和11个月放在同一条线上吗?我要如何或必须把它们放在不同的线上呢?”
发布于 2019-02-08 16:19:55
可以使用ViewPatterns
扩展来匹配应用于参数的任意函数的结果。(这可能不符合转换为模式匹配的精神,但我要说,它满足了任务的要求。)
{-# LANGUAGE ViewPatterns #-}
daysInMonth :: Int -> Int
daysInMonth (\x -> x < 0 || x > 12 -> True) = error "Month does not exist"
daysInMonth ((`elem` [4, 6, 9, 11]) -> True) = 30
daysInMonth 2 = 28
daysInMonth _ = 31
这也有助于进行简单的查找。(关联列表不完整以节省空间。)
daysInMonth :: Int -> Int
daysInMonth (flip lookup [(1,31), (2,28), (3,31), ...] -> Just d) = d
daysInMonth _ = error "Month does not exist"
在这里,我们应用lookup
返回一个Maybe Int
值,并将其与Just d
匹配。如果查找成功(对于有效的月份号应该是这样),则返回值d
。如果lookup
返回Nothing
,则模式匹配失败,我们将尝试下一个模式匹配,它为它所看到的任何输入调用error
。
(当然,这更简单地写成了daysInMonth = maybe (error "...") id . flip lookup [...]
,而不是求助于ViewPatterns
扩展,但我认为这是视图模式如何工作的一个很好的例子。)
发布于 2019-02-09 05:39:17
不知道我是否理解这个问题,让我试试看。
如果您确实需要删除保护,您可以匹配每个情况的输入值。但正如您所看到的,它将大大减少readability
。
在使用模式匹配时要小心,确保包含所有可能的情况。
下面的代码不是一个很好的例子,只是为了说明它是可行的。
daysInMonth :: Int -> Int
-- | m == 4 || m == 6 || m == 9 || m == 11 = 30
daysInMonth 4 = 30
daysInMonth 6 = 30
daysInMonth 9 = 30
daysInMonth 11 = 30
-- | m == 2 = 28
daysInMonth 2 = 28
-- | m > 12 || m < 0 = error "Month does not exist"
-- | m == m = 31
daysInMonth m = if (m > 12 || m < 0)
then error "Month does not exist"
else 31
https://stackoverflow.com/questions/54596132
复制相似问题