Your problem is that Pitch implicitly limited, i.e. has the smallest and largest element, but you do not reflect this limitation in your code. The code
[Pitch O1 A ..]
desugars to
enumFrom (Pitch O1 A)
which saves the succ generated values ββuntil there is a succ Pitch O3 F and explodes. How could he know that he should stop there?
From the Prelude documentation :
For any type that is an instance of the Bounded class, as well as Enum , the following should be done:
...
enumFrom and enumFromThen should be defined using an implied boundary, thus:
enumFrom x = enumFromTo x maxBound enumFromThen xy = enumFromThenTo xy bound where bound | fromEnum y >= fromEnum x = maxBound | otherwise = minBound
So, to fix this problem, just add
instance Bounded Pitch where minBound = Pitch minBound minBound maxBound = Pitch maxBound maxBound
and then add the code from the documentation:
instance Enum Pitch where -- ... enumFrom x = enumFromTo x maxBound enumFromThen xy = enumFromThenTo xy bound where bound | fromEnum y >= fromEnum x = maxBound | otherwise = minBound
and now [Pitch O1 A ..] will stop at the end:
Ξ»> [Pitch O1 A ..] [Pitch O1 A,Pitch O1 B,Pitch O1 C,Pitch O1 D,Pitch O1 E,Pitch O1 F,Pitch O2 A,Pitch O2 B,Pitch O2 C,Pitch O2 D,Pitch O2 E,Pitch O2 F,Pitch O3 A,Pitch O3 B,Pitch O3 C,Pitch O3 D,Pitch O3 E,Pitch O3 F]
Note: you can replace individual calls with div and mod to match the pattern with one call to divMod : x `divMod` y == (x `div` y, x `mod` y) . (For strictly positive numbers like these, I think I heard that quotRem might be the best choice; quot and rem are similar to div and mod , but with different registration-related behaviors.) Alternatively, you can replace 6 with 1 + (fromEnum (maxBound :: Note)) , so as not to accidentally make a mistake.