I am currently trying to implement a typeclass that allows me to convert any of custom types to an Integral (those types should all be convertible to an index or a weight). In this specific case I want to use it to make sure that a musical note, on a given octave, can be converted to the index of a piano keyboard key:
import Data.Int
class Convertible a where
toIntegral :: Integral b => a -> b
data Note = Note Tone Int
instance Convertible Note where
toIntegral (Note t o) = o * 12 + toIntegral t
However the compiler complains my implementation of toIntegral for Note does not comply with my Convertible typeclass.
• Couldn't match expected type ‘b’ with actual type ‘Int’
‘b’ is a rigid type variable bound by
the type signature for:
num :: forall b. Integral b => Note -> b
at src/Note.hs:11:5
• In the expression: octave * 12 + (num tone)
In an equation for ‘num’:
num (Note tone octave) = octave * 12 + (num tone)
In the instance declaration for ‘Convertible Note’
• Relevant bindings include
num :: Note -> b (bound at src/Note.hs:11:5)
As far as I understand, it considers the content of my toIntegral function evaluates to an a -> Int, when I constrained it to be an Integral => b -> a -> b. Now I don't understand what's wrong, because Int implements the Integral typeclass, right?
Can you help me understand what I'm obviously doing wrong here?