鉴于我有以下代码:
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
中的非详尽模式他们的代码和逻辑非常相似,所以我不知道什么是错的
另一件事:没有递归会有另一种方法来实现这种行为吗?
答案 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时,你需要处理这个案例。