非详尽的模式

时间:2015-08-05 19:51:06

标签: haskell non-exhaustive-patterns

鉴于我有以下代码:

data Note = C | Db | D | Eb | E | F | Gb | G | Ab | A | Bb | B
      deriving (Show, Eq, Ord, Enum)

next :: Note -> Note
next B = C
next n = succ n

previous :: Note -> Note
previous C = B
previous n = pred n

resolveAscendingInterval :: Int -> Note -> Note
resolveAscendingInterval 0 note = note
resolveAscendingInterval interval note = resolveAscendingInterval (interval -1) (next note)

resolveDescendingInterval :: Int -> Note -> Note
resolveDescendingInterval 0 note = note
resolveDescendingIInterval interval note = resolveDescendingIInterval (interval -1) (previous note)

main :: IO ()
    main = do
    print $ resolveAscendingInterval 3 C
    print $ resolveDescendingInterval 3 C

resolveAscendingInterval工作正常,但是当我运行resolveDescendingInterval时,我得到:

函数resolveDescendingInterval

中的非详尽模式

他们的代码和逻辑非常相似,所以我不知道什么是错的

另一件事:没有递归会有另一种方法来实现这种行为吗?

1 个答案:

答案 0 :(得分:4)

这只是一个错字。注意resolveDescendingIInterval是与resolveDescendingInterval不同的功能。摆脱额外的I

编辑:请考虑以下稍微不安全的代码:

resolveDecendingInterval interval note = toEnum (fromEnum note - interval)

这是一个部分功能 - 当间隔过大时会失败,我们会在超出范围的某个地方调用toEnum。您可以通过max (fromEnum (minBound :: Note)) . min (fromEnum (maxBound :: Note))等代码来限制范围。但是,我可能还有一种更聪明的方法,就是我不会马上思考。

另一种方法是通过interval来限制rem interval (fromEnum note),但是当注释是minBound时,你需要处理这个案例。