johnson
johnson

Reputation: 283

Haskell type specifier issue using integral and int

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

Answers (2)

Mark Seemann
Mark Seemann

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

Andrew Lei
Andrew Lei

Reputation: 325

I believe the problem here is you have to also declare nNotes to be of type nNotes :: Integral a => a.

Upvotes: 1

Related Questions