我在源文件中有以下Haskell定义
nNotes=7
pitchLimit k = k < 0 || k > 20
pitcherror = error "Invalid Pitch"
getOctave k
| pitchLimit k = pitcherror
| otherwise = k `div` nNotes
我没有声明getOctave
的类型。现在这是关于类型的问题。稍后在同一个源文件中,我使用了getOctave
Int
。我将源文件加载到GHCI中,Haskell推断getOctave
的类型是Int->Int
。现在,我将使用getOctave
作为Int
的代码注释掉。我重新加载源文件,现在Haskell推断getOctave
为Integer->Integer
类型。现在我觉得默认div
是Integer->Integer
。现在,我取消注释该代码并将getOctave
的类型指定为(Integral a) => a ->a
。 Haskell报告错误。使用(Integral a) => a -> a
时出了什么问题。
答案 0 :(得分:3)
当您使用像7
这样的文字时,GHC会尝试猜测您的意思。您可以使用.hs
文件(除了module
声明)仅包含
nNotes = 7
这将为您提供编译器警告:
* 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
从那里,编译器将推断所有其他类型。
您可以通过使用类型明确注释nNotes
来概括您的代码,如下所示:
nNotes :: Num a => a
nNotes = 7
执行此操作后,您的函数会自动获取这些类型:
λ: :type pitchLimit
pitchLimit :: (Ord a, Num a) => a -> Bool
λ: :type getOctave
getOctave :: Integral t => t -> t
如您所见,getOctave
可以将Integral
作为输入,包括Integer
和Int
。
getOctave
推断t
成为班级Integral
的原因是因为div
定义了Integral
。
答案 1 :(得分:1)
我认为这里的问题是你必须声明nNotes是nNotes :: Integral a => a
类型。