函数类型声明错误

时间:2020-05-16 14:16:00

标签: haskell

我具有以下功能,该功能只能从列表中返回奇数

oddsOnly :: Integral a => [a] -> [a]
oddsOnly [] = []
oddsOnly (x:xs)
 |odd x = x : oddsOnly xs
 |otherwise = oddsOnly xs

我的问题是关于使用

的目的

积分a =>

实际上,用这样的类型声明来实现该功能是不可能的

oddsOnly :: [a]-> [a]

据我所知, even odd 函数位于标准的 Prelude 库中,所以为什么简化的声明不起作用?

预先感谢

3 个答案:

答案 0 :(得分:9)

为什么简化的声明不起作用?

因为您无法判断字符串是否为奇数。或者,如果一个浮点数是奇数或不是。通常,无法判断任何类型a的值是否为奇数,因为可能没有为该类型定义奇数的概念。

但是,为Integral类型定义了 ,因此您必须指定aIntegral

就Haskell而言,odd仅适用于Integral s:

Prelude> :t odd
odd :: Integral a => a -> Bool

因此,您必须向其传递类型为Integral的值。

答案 1 :(得分:8)

oddeven的签名分别为odd :: Integral a => a -> Booleven :: Integral a => a -> Bool。因此它们包含Integral a type constraint [Haskell-wiki]

类型约束与定义的位置无关。它指定仅为类型的子集定义函数。仅对于属于Integral typeclass成员的类型,您可以使用该函数。整数类型是指定a的子集的类型,因此IntInt64Word8Integer,…类型。 oddevenFloatStringChar等上没有多大意义。这是什么意思?

通过指定Integral a =>类型约束,可以指定此函数只能用于类似整数的项目。

请注意,您可以在此处使用filter :: (a -> Bool) -> [a] -> [a]仅保留奇数:

oddsOnly :: Integral a => [a] -> [a]
oddsOnly = filter odd

答案 2 :(得分:3)

让我们看一下oddodd :: Integral a => a -> Bool的类型签名。因此,要将odd与参数一起使用,该参数必须为Integral。这在直觉上是有道理的:正如@ForceBru在另一个答案中所说,您无法分辨是否诸如1.5之类的浮点数或诸如"hello"之类的字符串是奇数,因为奇数的概念仅针对整数值定义。