Reputation: 283
I have the following Haskell definitions in a source file
nNotes=7
pitchLimit k = k < 0 || k > 20
pitcherror = error "Invalid Pitch"
getOctave k
| pitchLimit k = pitcherror
| otherwise = k `div` nNotes
I do not declare the type of getOctave
. Now here is my issue regarding types. Later on in the same source file, I used getOctave
with an Int
. I load the source file into GHCI and Haskell infers that the type of getOctave
is Int->Int
. Now I comment out the code that uses getOctave
as an Int
. I reload the source file and now Haskell infers getOctave
to be of type Integer->Integer
. Seems to me now that the default of div
is Integer->Integer
. Now I uncomment that code and specify the type of getOctave
to be (Integral a) => a ->a
. And Haskell reports an error. What's wrong with using (Integral a) => a -> a
.
Upvotes: 3
Views: 118
Reputation: 233457
When you use a literal like 7
, GHC tries to guess which type you meant. You can reproduce this with a .hs
file that (apart from a module
declaration) contains only
nNotes = 7
This will give you the compiler warning:
* Defaulting the following constraint to type `Integer'
Num t0 arising from the literal `7'
* In the expression: 7
In an equation for `nNotes': nNotes = 7
From there, the compiler will infer all the other types.
You can generalise your code by explicitly annotate nNotes
with a type, like this:
nNotes :: Num a => a
nNotes = 7
Once you do that, your functions get these automatically inferred types:
λ: :type pitchLimit
pitchLimit :: (Ord a, Num a) => a -> Bool
λ: :type getOctave
getOctave :: Integral t => t -> t
As you can see, getOctave
can take any Integral
as input, including both Integer
and Int
.
The reason that getOctave
infers t
to be of the class Integral
is because div
is defined for Integral
.
Upvotes: 3
Reputation: 325
I believe the problem here is you have to also declare nNotes to be of type nNotes :: Integral a => a
.
Upvotes: 1