Non-exhaustive patterns [closed]

2019-03-06 17:44发布

问题:

Given I have the following code:

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 works fine, but when I run resolveDescendingInterval I get:

Non-exhaustive patterns in function resolveDescendingInterval

Their code and logic are very similar, so I don't have a clue of whats wrong

Another thing: Is there another way to achieve this behavior without recursion?

回答1:

This is just a typo. Notice resolveDescendingIInterval is a different function from resolveDescendingInterval. Get rid of that extra I.

EDIT: Consider the following slightly unsafe code:

resolveDecendingInterval interval note = toEnum (fromEnum note - interval)

This is a partial function - it will fail when the interval is too large and we call toEnum on something out of range. You can clamp the range via code such as max (fromEnum (minBound :: Note)) . min (fromEnum (maxBound :: Note)). But there's probably a smarter way I'm just not thinking off immediately.

One alternative would be to clamp the interval via rem interval (fromEnum note) but then you'll need to handle the case when note is minBound separately.