【问题标题】:Haskell type specifier issue using integral and int使用整数和 int 的 Haskell 类型说明符问题
【发布时间】:2017-08-28 16:23:26
【问题描述】:

我在源文件中有以下 Haskell 定义

nNotes=7

pitchLimit k = k < 0 || k > 20  
pitcherror = error "Invalid Pitch"

getOctave k
    | pitchLimit k = pitcherror
    | otherwise = k `div` nNotes

我没有声明getOctave 的类型。现在这是我关于类型的问题。后来在同一个源文件中,我使用了getOctaveInt。我将源文件加载到 GHCI 中,Haskell 推断getOctave 的类型是Int-&gt;Int。现在我注释掉使用getOctave 作为Int 的代码。我重新加载源文件,现在 Haskell 推断 getOctave 的类型为 Integer-&gt;Integer。现在在我看来div 的默认值是Integer-&gt;Integer。现在我取消注释该代码并将getOctave 的类型指定为(Integral a) =&gt; a -&gt;a。 Haskell 报错。使用(Integral a) =&gt; a -&gt; a 有什么问题。

【问题讨论】:

标签: haskell types


【解决方案1】:

当您使用像 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 定义的。

【讨论】:

    【解决方案2】:

    我认为这里的问题是您还必须将 nNotes 声明为 nNotes :: Integral a =&gt; a 类型。

    【讨论】:

    • 这很有趣。我忘记了nNotes。 Haskell 推断它的类型为Int。为什么?
    • @johnson 当我在 ghci 中加载源文件时,它看起来假设 nNotes 是Integer。当您在代码中有其他类型为Int 时,编译器可能会意识到nNotes 必须是Int。我的猜测是,除非相互矛盾,否则编译器假定整数文字定义应该是Integer。在这种情况下,如果 GHC 不能自动推断您希望 nNotes 的类型为 Integral a =&gt; a (但我对编译器了解不多),则可能是 GHC 的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    相关资源
    最近更新 更多