非穷尽模式
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
中的非详尽模式
他们的代码和逻辑非常相似,所以我不知道哪里出了问题
另一件事:是否有另一种方法可以在不递归的情况下实现这种行为?
这只是一个错字。注意 resolveDescendingIInterval
与 resolveDescendingInterval
是不同的函数。去掉多余的 I
.
编辑:考虑以下稍微不安全的代码:
resolveDecendingInterval interval note = toEnum (fromEnum note - interval)
这是一个部分函数 - 当间隔太大并且我们在超出范围的地方调用 toEnum
时它会失败。您可以通过 max (fromEnum (minBound :: Note)) . min (fromEnum (maxBound :: Note))
等代码限制范围。但可能有一个更聪明的方法,我只是没有立即考虑。
一种替代方法是通过 rem interval (fromEnum note)
限制 interval
,但是当 note 是 minBound 时,您需要单独处理这种情况。
鉴于我有以下代码:
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
中的非详尽模式他们的代码和逻辑非常相似,所以我不知道哪里出了问题
另一件事:是否有另一种方法可以在不递归的情况下实现这种行为?
这只是一个错字。注意 resolveDescendingIInterval
与 resolveDescendingInterval
是不同的函数。去掉多余的 I
.
编辑:考虑以下稍微不安全的代码:
resolveDecendingInterval interval note = toEnum (fromEnum note - interval)
这是一个部分函数 - 当间隔太大并且我们在超出范围的地方调用 toEnum
时它会失败。您可以通过 max (fromEnum (minBound :: Note)) . min (fromEnum (maxBound :: Note))
等代码限制范围。但可能有一个更聪明的方法,我只是没有立即考虑。
一种替代方法是通过 rem interval (fromEnum note)
限制 interval
,但是当 note 是 minBound 时,您需要单独处理这种情况。