文章
Get Programming with Haskell-4
函数是一等公民
部分内容超过 Notion API 单页读取上限,已尽力加载可访问内容。
ifEvenSquare n = if even n then n ^ 2 else n
这些个函数其实都是一个模式,都是判断参数n是不是even,如果是则进行“**某种操作**”,否则直接返回n,我们抽象一个这种模式,将这“某种操作”是不是可以抽象成一个function,然后重新梳理以下这类函数的模式,参数n如果是even, 我们就function n,否则返回n,然后就是这种形式了
```haskell
ifEven myFunc n = if even n
then myFunc n
else n
这个myFunc 可以是 inc n = n + 1 , double n = n * 2, square n = n ^ 2等等等,测试一下这个是否可行:
事实证明,这个完全是可行的,那么我们是不是可以推广一下这个函数,其实n → n也是一个函数
ifEven1 myFunc1 myFunc2 n = if even n
then myFunc1 n
else myFunc2 n
已经显而易见了,一切都是这么自然合乎逻辑
1、Lambda functions as arguments#
上一节我们都是用命名函数,那么用lambda是不是也可以呢,当然,因为理论上所有的命名函数都可以和匿名函数互换
ifEven (\x -> x + 1) 3
2、Example—custom sorting#
将函数作为参数传递给另外一个函数最实际的用途是排序,下面的example中我们会使用tuple和list,tuple是一种和列表相似的数据类型,只不过tuple可以存放多种不同类型的元素且存放元素的大小个数是固定:
author = (”Will”, “Kurt”)
这种只有2个item的tuple(又称作a pair)有两个有用的函数,fst和snd,作用分别是访问tuple的第一个和第二个元素
names = [("Ian", "Curtis"),
("Bernard", "Summer)",
("Peter", "Hook"),
("Stephen", "Morris")
]
对于list的排序haskell中已经有了内置的排序函数sort。要使用它,我们要import Data.List模块,使用方式如下:
import Data.List
从这个排序结果看,是按照first name的字母表顺序来排序的,那么我们如果想按照last name来排序怎么办呢?当然这是一种常规需求,Haskell在Data.List模块中也提供了相应的函数 sortBy,sortBy有一个自定义排序的方式的函数作为参数,我们可以定义一个按last name大小升序来排序的函数,使用方式是这样的:
compareLastName name1 name2 = if lastName1 > lastName2
then GT
else if lastName1 < lastName2
then LT
else EQ
where lastName1 = snd name1
lastName2 = snd name2
2、Returning functions#
我们已深入探讨了将函数作为参数传递(passing functions as arguments)的诸多应用,但这仅展现了一等函数(first-class functions)作为值的能力之半壁。函数亦可返回值,因此真正的"一等公民"函数,必然包含返回其他函数(return other functions)的能力。此时开发者不禁要问:为何需要返回函数呢? 一个典型场景是——基于特定参数动态分派函数(dispatch functions)。
- PO Box 1234,San Francisco,CA,94111
- PO Box 789,New York,NY,10013
- PO Box 456,Reno,NV,89523
您需要构建一个函数,该函数将接受一个名称tuple(如您之前在排序示例中使用的那样) 和一个办公室位置,然后为您整理邮件地址。此函数的第一遍可能如下所示。我们需要介绍的唯一一件你还没有看到的事情是用于连接字符串 (和列表) 的
++运算符。
addressLetter name location = nameText ++ " - " ++ location
where
nameText = (fst name) ++ " " ++ (snd name)