这是面向初学者的函数式语言 Haskell 系列的第二篇。1
感谢您进入Haskell系列的第二部分,您可以在这里找到上一篇文章,我对 Haskell 类型和函数的快速介绍。
正如承诺的那样,我们将在本文中介绍的是:列表和函数声明。让我们先从列表开始,因为这是下一部分的基础:
列表
列表是 Haskell 中的基本要素,并且是最常用的数据结构:
Prelude> a = [1, 2, 3, 4, 5]
Prelude> head a
1
Prelude> last a
5
Prelude> length a
5
一些开箱即用的函数可以帮助我们处理列表:head
返回列表的第一个元素,last
返回列表的最后一个元素(小心,它不是 tail
,tail
会给你除了第一个元素之外,剩余元素组成的列表),length
返回列表中的元素个数。十分简单。
列表非常通用,您可以简单地将它们连接在一起,如下所示:
Prelude> a = [1,2,3,4,5]
Prelude> b = [6,7,8]
Prelude> a ++ b
[1,2,3,4,5,6,7,8]
您会注意到在 Haskell 中我们区分了+
(add/加号) 和++
(concatenate/连接)。
为了访问特定索引,您可以使用以下内容:
Prelude> a
[1,2,3,4,5]
Prelude> a !! 0
1
Prelude> a !! 1
2
根据我们上面讲述的知识,您可以在列表的开头或结尾添加一个元素,如下所示:
Prelude> a ++ [6]
[1,2,3,4,5,6]
Prelude> [0] ++ a
[0,1,2,3,4,5]
列表推导式
现在,让我们看看列表推导式,如果您使用过Python,您就会知道发生了什么。如果没有使用过,请将其视为迭代列表并应用一些操作以获取新列表的表达式。
让我们做一个 Haskell/Python 的比较,我们将把列表中的每个元素都加倍:
Haskell 中的示例:
Prelude> a = [1,2,3,4,5]
Prelude> [x * 2 | x <- a]
[2,4,6,8,10]
Python 中的示例:
>>> a = [1,2,3,4,5]
>>> [x * 2 for x in a]
[2, 4, 6, 8, 10]
看起来非常相似,表达式用方括号括起来。在 Haskell 版本中,我们使用管道|
来分割我们将对列表每个元素执行的操作(左)和列表的源(右)。
现在,我们想过滤掉数字 3,可以这样做:
Haskell 中的示例:
Prelude> a = [1,2,3,4,5]
Prelude> [x * 2 | x <- a, x /= 3]
[2,4,8,10]
Python 中的示例:
>>> a = [1,2,3,4,5]
>>> [x * 2 for x in a if x != 3]
[2, 4, 8, 10]
您会注意到,在 Haskell 中,我们使用/=
检查不等式,而不是大多数语言中的常用方法!=
。还有一件事,在 Haskell 中,谓词是用,
分隔的,这意味着你可以把很多个谓词放在一起,而不是写elif
,or
等等。例如:
Prelude> a = [1,2,3,4,5]
Prelude> [x * 2 | x <- a, x /= 3, x /= 4, x /= 5]
[2,4]
函数声明
在我们之前的文章中,我们对函数进行了快速介绍,作为入门,我们写了以下代码:
powerOfTwo x = powerOfX x 2
powerOfThree x = powerOfX x 3
powerOfX x y = x ** y
这些是计算数字的幂的简单函数。
在 Haskell 中,您可以编写函数的实现,但是使用Haskell来编写函数定义也是一种很好的体验。毕竟,它是一种静态类型语言,如果不提函数的类型,那将是一个巨大的损失。
让我们在fn.hs
文件中编写powerOfTwo
函数:
powerOfTwo :: Float -> Float
很好,在计算出结果之前,让我们来定义powerOfX
函数:
powerOfX :: Float -> Float -> Float
对,基本上,我们不必区分参数和返回值,我们将在稍后解释。到目前为止,让我们记住返回值是右边的最后一个。
当然,我们可以使用一个非常有用的命令来检查我们的函数,:t
。如下所示:
*Main> :t powerOfTwo
powerOfTwo :: Float -> Float
*Main> :t powerOfX
powerOfX :: Float -> Float -> Float
现在我们了解了列表,函数声明和实现,让我们将这些混合起来。
我们将编写一个函数,它接受一个Float
的数组并计算它们的 x 的幂。让我们创建一个新文件power.hs
:
-- This is our function from fn.hs which we just copy/pasted here
powerOfX :: Float -> Float -> Float
powerOfX x y = x ** y
-- This is our new function which goes through a list
powerOfXForList :: [Float] -> Float -> [Float]
powerOfXForList list y = [powerOfX x y | x <- list]
让我们解释一下powerOfXForList
函数的定义:我们将输入两个参数:
[Float]
类型的list
(这是我们的底数列表)Float
类型的y
(这是我们的指数)
我们将返回 一 个[Float]
,它是一个与第一个参数类型相同的新列表,除了每个元素都将被计算为它自己y
次幂。
然后,就像我们在第一篇文章中看到的,在ghci
中用:l <filename>
加载它:
*Main> :l power.hs
[1 of 1] Compiling Main ( power.hs, interpreted )
Ok, one module loaded.
我们的函数已经加载到环境中了,我们可以测试一下:
*Main> a = [1,2,3,4,5]
*Main> powerOfXForList a 2
[1.0,4.0,9.0,16.0,25.0]
*Main> powerOfXForList a 3
[1.0,8.0,27.0,64.0,125.0]
一切看起来都不错,现在我们完成了。在下一篇文章开始之前让我们休息一下。
结论
希望这篇文章能激发一些你的好奇心。在下一篇文章中,我们将讨论中缀函数与前缀函数,并了解有关类型的更多信息。
本文翻译自Haskell series part 2 ↩︎