使用integral和int的Haskell类型说明符问题

时间:2017-08-28 05:33:13

标签: haskell types

我在源文件中有以下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推断getOctaveInteger->Integer类型。现在我觉得默认divInteger->Integer。现在,我取消注释该代码并将getOctave的类型指定为(Integral a) => a ->a。 Haskell报告错误。使用(Integral a) => a -> a时出了什么问题。

2 个答案:

答案 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作为输入,包括IntegerInt

getOctave推断t成为班级Integral的原因是因为div定义了Integral

答案 1 :(得分:1)

我认为这里的问题是你必须声明nNotes是nNotes :: Integral a => a类型。