Неисчерпывающие закономерности
Учитывая, что у меня есть следующий код:
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
resolAscendingInterval работает нормально, но когда я запускаю resolDescendingInterval, я получаю:
Неполные шаблоны в функции resolDescendingInterval
Их код и логика очень похожи, поэтому я понятия не имею, что не так
Другое дело: есть ли другой способ добиться этого поведения без рекурсии?
1 ответ
Это просто опечатка. уведомление 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 отдельно.