在Haskell中获取int或integer的总和

时间:2017-07-30 02:24:06

标签: haskell

此函数应适用于Int列表和Integer列表:

myFunc :: [Integer] -> [Char]
myFunc x =  if (sum x `mod` 2 ==1) then "odd" else "even"

但它只适用于整数列表。

2 个答案:

答案 0 :(得分:7)

类型类提供了一种关于类型的通用方法(它们实际上是类型组)。您可以使用类型类约束而不是显式类型Integer,如下所示:

myFunc :: Integral a => [a] -> String
myFunc x = if (even (sum x)) then "even" else "odd"

这样做是指明它是[a]String的函数,其中a是一个类型变量,只要它是一个成员,它就被约束为任何类型Integral类型类。另一种说法是任何类型,只要它具有Integral类型类的实例即可。这意味着它具有为该特定类型指定的类型类的方法。

Integral类型类用于值为整数的类型(即积分)。

很高兴IntInteger都为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]),编译器将自动填充空白这对你来说。类型声明用于阐明函数的类型,限制函数的适用性,或者向编译器说明变量在由于某种原因无法推断类型时的类型。但是,如果您不想,您通常不必申报该类型。