-1

鉴于我有以下代码:

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 中的非详尽模式

他们的代码和逻辑非常相似,所以我不知道出了什么问题

另一件事:有没有另一种方法可以在没有递归的情况下实现这种行为?

4

1 回答 1

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)但是当 note 是 minBound 时,您需要单独处理这种情况。

于 2015-08-05T19:53:20.693 回答