当前位置: 首页 > 工具软件 > Haskell > 使用案例 >

Haskell初学指南(二)

宰父淳
2023-12-01

这是面向初学者的函数式语言 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返回列表的最后一个元素(小心,它不是 tailtail会给你除了第一个元素之外,剩余元素组成的列表),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 中,谓词是用,分隔的,这意味着你可以把很多个谓词放在一起,而不是写elifor等等。例如:

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]

一切看起来都不错,现在我们完成了。在下一篇文章开始之前让我们休息一下。

结论

希望这篇文章能激发一些你的好奇心。在下一篇文章中,我们将讨论中缀函数与前缀函数,并了解有关类型的更多信息。


  1. 本文翻译自Haskell series part 2 ↩︎

 类似资料: