模式匹配不同的输入相同的输出haskell

时间:2019-02-08 15:59:55

标签: haskell

我有一个输出一个月中的天数的功能,需要更换防护装置并使用模式匹配。 `

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个月保持在同一行中,还是必须将它们放在不同的行中?

2 个答案:

答案 0 :(得分:2)

您可以使用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扩展名,但我虽然是一个很好的示例,说明了视图模式的工作原理。)

答案 1 :(得分:0)

不确定我是否理解问题,让我尝试。

如果您确实需要删除防护,则可以针对每种情况匹配输入值。但是如您所见,它将大大减少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