在 Haskell 中返回特定类型

Posted

技术标签:

【中文标题】在 Haskell 中返回特定类型【英文标题】:Return specific type within Haskell 【发布时间】:2010-12-04 18:55:50 【问题描述】:

我对 Haskell 的类型系统有一个非常普遍的问题。我正在努力熟悉它,我有以下功能:

getN :: Num a => a
getN = 5.0 :: Double

当我尝试编译它时,我收到以下错误:

Couldn't match expected type `a' against inferred type `Double'
  `a' is a rigid type variable bound by
      the type signature for `getN' at Perlin.hs:15:12
In the expression: 5.0 :: Double
In the definition of `getN': getN = 5.0 :: Double

据我了解,该函数设置为“返回”类 Num 中的一个类型。 Double 属于此类 (http://www.zvon.org/other/haskell/Outputprelude/Num_c.html),所以我原以为在这种情况下“返回”一个 Double 是可以的。

有人可以解释一下吗?

【问题讨论】:

【参考方案1】:

签名为Num a => a 的函数应适用于Num 类中的任何 类型。实现5.0 :: Double 仅适用于 one 类型,不适用于类的 所有 类型,因此编译器会抱怨。

一个泛型函数的例子是:

square :: (Num a) => a -> a
square x = x * x

这适用于Num任何 类型。它适用于双精度数、整数和您想要使用的任何其他数字。正因为如此,它可以有一个泛型类型签名,只要求参数在类Num 中。 (类型类Num 是必需的,因为该函数使用与* 的乘法,这是在那里定义的)

【讨论】:

+1 - 我们可以将上述函数类型写成forall a . Num a => a -> 它必须适用于任何类型。【参考方案2】:

补充一下答案:Haskell 不是面向对象的。 Double 不是 Num 的子类,这不是真的,因此如果您承诺返回多态 Num 值,则不能返回 Double,就像在 Java 中一样。

当您编写getN :: Num a => a 时,您承诺返回一个在Num 约束内完全多态的值。实际上,这意味着您只能使用 Num 类型类中的函数,例如 +*-fromInteger

【讨论】:

【参考方案3】:

查看存在量化类型

解决它的一种方法是定义一个新的数据类型

data NumBox = forall n. Num n => NumBox n

您需要-XExistentialQuantification 才能使其正常工作。

现在你可以写类似的东西

getN :: NumBox
getN = NumBox (5.0 :: Double)

您还可以将NumBox-list 定义为

let n3 = [NumBox (4.0 :: Double), NumBox (1 :: Integer), NumBox (1 :: Int) ]

【讨论】:

以上是关于在 Haskell 中返回特定类型的主要内容,如果未能解决你的问题,请参考以下文章

在haskell中故意定义无限类型

Haskell文件I / O返回类型不匹配?

如何在 Haskell 函数中对递归数据类型进行递归

为什么Haskell函数定义里面返回参数和返回类型都用 -> 分隔

对 Haskell 类型推断感到困惑

Haskell中有序数字类型的“signum”用例