此函数应适用于Int列表和Integer列表:
myFunc :: [Integer] -> [Char]
myFunc x = if (sum x `mod` 2 ==1) then "odd" else "even"
但它只适用于整数列表。
答案 0 :(得分:7)
类型类提供了一种关于类型的通用方法(它们实际上是类型组)。您可以使用类型类约束而不是显式类型Integer
,如下所示:
myFunc :: Integral a => [a] -> String
myFunc x = if (even (sum x)) then "even" else "odd"
这样做是指明它是[a]
到String
的函数,其中a
是一个类型变量,只要它是一个成员,它就被约束为任何类型Integral
类型类。另一种说法是任何类型,只要它具有Integral
类型类的实例即可。这意味着它具有为该特定类型指定的类型类的方法。
Integral
类型类用于值为整数的类型(即积分)。
很高兴Int
和Integer
都为Integral
提供了一个实例,因此我们可以使用它。
答案 1 :(得分:4)
Int和Integers是不同的类型。它们都是Integral类型类的实例,然而,它们具有' mod'作为其功能之一。
为了让你的功能适用于特定类型以外的东西,你想要做的就是说这个函数,而不是[Integer] - > [Char]或[Int] - > [Char],类型应该比其中一个更少限制;它应该是[a] - > [字符]。但是如果你声明了那个实例,它就不会编译,因为有两件事:
1)总和要求你的x是一个数字列表。也就是说,
sum :: Num a => [a] -> a;
Num是另一个类型类,它需要任何类型为Num to include a definition for (+)的实例,等等;这允许sum使用加法来添加所有数字。
2)mod要求你的x之和具有一个Integral实例的类型。所以
mod (sum x) :: Integral a => a -> a
从技术上讲,它还要求类型是Num的实例,因为sum x必须是,但definition of Integral要求Integral的任何实例也是Real的实例,这反过来又需要它的类型为Num - 基本上你可以要求数字为实例Num的免费类型。
所以,最后,你需要让第一种类型成为变量' (并不真正知道它的用语)类型,但必须是Integral类型的那个:
myFunc :: Integral a => [a] -> [Char]
myFunc x = if (sum x `mod` 2 ==1) then "odd" else "even"
此外,如果您不包含类型声明(即myFunc :: Integral a => [a] - > [Char]),编译器将自动填充空白这对你来说。类型声明用于阐明函数的类型,限制函数的适用性,或者向编译器说明变量在由于某种原因无法推断类型时的类型。但是,如果您不想,您通常不必申报该类型。