我具有以下功能,该功能只能从列表中返回奇数
oddsOnly :: Integral a => [a] -> [a]
oddsOnly [] = []
oddsOnly (x:xs)
|odd x = x : oddsOnly xs
|otherwise = oddsOnly xs
我的问题是关于使用
的目的积分a =>
实际上,用这样的类型声明来实现该功能是不可能的
oddsOnly :: [a]-> [a]
据我所知, even 和 odd 函数位于标准的 Prelude 库中,所以为什么简化的声明不起作用?
预先感谢
答案 0 :(得分:9)
为什么简化的声明不起作用?
因为您无法判断字符串是否为奇数。或者,如果一个浮点数是奇数或不是。通常,无法判断任何类型a
的值是否为奇数,因为可能没有为该类型定义奇数的概念。
但是,为Integral
类型定义了 ,因此您必须指定a
是Integral
。
就Haskell而言,odd
仅适用于Integral
s:
Prelude> :t odd
odd :: Integral a => a -> Bool
因此,您必须向其传递类型为Integral
的值。
答案 1 :(得分:8)
odd
和even
的签名分别为odd :: Integral a => a -> Bool
和even :: Integral a => a -> Bool
。因此它们包含Integral a
type constraint [Haskell-wiki]。
类型约束与定义的位置无关。它指定仅为类型的子集定义函数。仅对于属于Integral
typeclass成员的类型,您可以使用该函数。整数类型是指定a的子集的类型,因此Int
,Int64
,Word8
,Integer
,…类型。 odd
和even
在Float
,String
,Char
等上没有多大意义。这是什么意思?
通过指定Integral a =>
类型约束,可以指定此函数只能用于类似整数的项目。
请注意,您可以在此处使用filter :: (a -> Bool) -> [a] -> [a]
仅保留奇数:
oddsOnly :: Integral a => [a] -> [a]
oddsOnly = filter odd
答案 2 :(得分:3)
让我们看一下odd
:odd :: Integral a => a -> Bool
的类型签名。因此,要将odd
与参数一起使用,该参数必须为Integral
。这在直觉上是有道理的:正如@ForceBru在另一个答案中所说,您无法分辨是否诸如1.5
之类的浮点数或诸如"hello"
之类的字符串是奇数,因为奇数的概念仅针对整数值定义。