《Haskell趣学指南》—— 第1章,第1.2节小朋友的第一个函数

简介: 本节书摘来自异步社区《Haskell趣学指南》一书中的第1章,第1.2节小朋友的第一个函数,作者 【斯洛文尼亚】Miran Lipovaca,更多章节内容可以访问云栖社区“异步社区”公众号查看 1.2 小朋友的第一个函数 函数的声明与它的调用形式大体相同,都是先函数名,后跟由空格分隔的参数表。

本节书摘来自异步社区《Haskell趣学指南》一书中的第1章,第1.2节小朋友的第一个函数,作者 【斯洛文尼亚】Miran Lipovaca,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.2 小朋友的第一个函数
函数的声明与它的调用形式大体相同,都是先函数名,后跟由空格分隔的参数表。不过后面多了个等号(=),并且后面的代码定义了函数的行为。

举个例子,我们先写一个简单的函数,让它将一个数字乘以2。打开你最喜欢的编辑器,输入如下代码:

doubleMe x = x + x

将它保存为baby.hs或者任意名称,然后转至文件所在目录,打开GHCi,执行:l baby装载它。随后就可以跟我们的函数小朋友玩耍了:

ghci> :l baby
[1 of 1] Compiling Main             ( baby.hs, interpreted ) 
Ok, modules loaded: Main. 
ghci> doubleMe 9
18
ghci> doubleMe 8.3
16.6

+运算符对整数和浮点数都可用(实际上所有有数字特征的值都可以),所以我们的函数可以处理一切数值。

接下来声明一个取两个参数的函数,让它分别将两个参数乘以2再相加。修改baby.hs,将如下代码加到后面:

doubleUs x y = x * 2 + y * 2

注意:
Haskell中的函数定义并没有顺序的概念,所以baby.hs中函数定义的先后对程序没有任何影响。
将它保存,在GHCi中输入:l baby再次装载。测试它的结果是否符合预期:

ghci> doubleUs 4 9
26
ghci> doubleUs 2.3 34.2
73.0
ghci> doubleUs 28 88 + doubleMe 123
478

你也可以在函数中调用其他的函数,如此一来我们可以将doubleUs函数改为:

doubleUs x y = doubleMe x + doubleMe y

这种模式在Haskell中十分常见:编写一些明显正确的简单函数,然后将它们组合起来,形成一个较为复杂的函数。这是减少重复工作的金科玉律。设想,如果哪天有个数学家验证说2其实该是3,我们该怎么改?在这里,我们只需要将doubleMe改为x+x+x即可,由于doubleUs调用doubleMe,于是整个程序便轻松进入2即是3的古怪世界。

下面我们再编写一个函数, 它将小于等于100的数都乘以2 (因为大于100的数都已经足够大了)。

doubleSmallNumber x = if x > 100
                      then x
                      else x*2

这个例子就引出了Haskell的if语句。你也许已经对其他语言的else很熟悉,不过Haskell的if语句的与众不同之处就在于,else部分是不可省略的。

在命令式语言中,程序的执行就是一步又一步的操作,if语句可以没有else部分,如果条件不符合,就直接跳过这一步。因此,命令式语言中的if语句可以什么都不做。

而在Haskell中,程序是一系列函数的集合:函数取数据作为参数,并将它们转为想要的结果。每个函数都会返回一个结果,也都可以为其他函数所用。既然必须返回结果,那么每个if就必须同时跟着一个else,不管条件满足还是失败,都需要返回一个结果。一言以蔽之,Haskell中的if是一个必然返回结果的表达式(expression),而非语句(statement)。

假如我们想让之前的doubleSmallNumber函数的结果都加1,新的函数的定义将是如下的模样:

doubleSmallNumber' x = (if x > 100 then x else x*2) + 1

可以留意这里括号的使用,如果忽略掉括号,函数就会只在x小于等于100时给结果加1了。另外,也可以留意函数名最后的那个单引号,它没有任何特殊含义,只是一个函数名的合法字符罢了。通常我们会使用单引号来区分这是某函数的严格求值(与惰性求值相对)版本,或者是一个稍经修改但差别不大的函数。

既然'是合法字符,定义这样的函数也是可以的:

conanO'Brien = "It's a-me, Conan O'Brien!" 

在这里有两点需要注意。首先就是我们没有大写Conan的首字母,因为函数是不能以大写字母开始的(我们将在后面讨论其原因 0,另外就是这个函数并没有任何参数。没有参数的函数通常被称作定义或者名字,在函数被定义之后我们就再也不能修改它的内容,conanO'Brien从此与字符串"It's a-me, Conan O'Brien!"完全等价。

相关文章
|
1月前
|
算法 编译器 C语言
C语言猜数字小游戏(也包含python实现的用法)
本文基于VS2022、pycharm和前面的知识,写一个凭借分支与循环的小游戏,比如: 写一个猜数字游戏 游戏要求: 电脑自动生成1~100的随机数 玩家猜数字,猜数的过程中,根据猜测数据的大小给出大了或小了的反馈,直到猜对,游戏结束 在pyhton中生成随机数是比较简单的,可以直接导入random的包,直接生成随机数,导致写猜数字小游戏变成了判读语句和循环语句嵌套就能写出来,所以我不做过多的介绍了,可以直接看后面的代码展示,想了解更多的python可看python的基础知识,这里面有我在学习python的过程中写的笔记
30 0
|
3月前
谭浩强数组相关代码
谭浩强数组相关代码
16 0
|
5月前
|
算法 搜索推荐 程序员
C语言第十五练——输出第n位的斐波那契数
C语言第十五练——输出第n位的斐波那契数
57 0
|
2月前
|
算法 搜索推荐 程序员
C语言第十七练——输出二进制中1的个数
C语言第十七练——输出二进制中1的个数
22 0
|
5月前
|
算法 搜索推荐 程序员
C语言第十六练——数字组合匹配
C语言第十六练——数字组合匹配
58 0
|
9月前
|
C语言
【C语言】第一个C语言项目——“猜数字”游戏(内附源码)
【C语言】第一个C语言项目——“猜数字”游戏(内附源码)
83 0
|
11月前
|
人工智能 机器人 数据挖掘
python第一个程序,定位在小学数学还是幼儿园?
python第一个程序,定位在小学数学还是幼儿园?
c语言 - 杨氏矩阵,查找某个数字(思路清晰,代码简洁)(适合刚入坑)
c语言 - 杨氏矩阵,查找某个数字(思路清晰,代码简洁)(适合刚入坑)
c语言 - 杨氏矩阵,查找某个数字(思路清晰,代码简洁)(适合刚入坑)
|
Python
Python经典编程习题100例:第27例:递归打印字符
Python经典编程习题100例:第27例:递归打印字符
84 0
使用 Lambda 表达式的正确姿势,写得太好了叭
Lambda 表达式非常方便,在项目中一般在 stream 编程中用得比较多。 List<Student> studentList = gen(); Map<String, Student> map = studentList .stream() .collect(Collectors.toMap(Student::getId, a -> a, (a, b) -> a)); 理解一个 Lambda 表达式就三步: 1. 确认 Lambda 表达式的类型 2. 找到要实现的方法 3. 实现这个方法 就这三步,没其他的了。而每一步,都非常非常简单,以至于我分别展开讲一下,你就懂了。

热门文章

最新文章