返回文章列表

文章

Get Programming with Haskell-4

函数是一等公民

部分内容超过 Notion API 单页读取上限,已尽力加载可访问内容。

目录
  1. 1、Lambda functions as arguments
  2. 2、Example—custom sorting
  3. 2、Returning functions
  4. 使用动态分派
# First-class functions ## 1、Functions as arguments 函数作为参数,先看以下示例: ```haskell ifEvenInc n = if even n then n + 1 else n ``` ifEvenInc函数有一个参数n,如果n是even,则函数返回n+1,否则返回n,很简单,测试一下: ![](https://prod-files-secure.s3.us-west-2.amazonaws.com/4b1b167f-4b52-4031-8233-f4f2689af574/45f3acbe-1e7a-429a-9fcb-65653eab4e76/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB4665I7VG43L%2F20260827%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260827T181910Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEHEaCXVzLXdlc3QtMiJGMEQCIDg1uw7rmQvSuzluufBoRUvdX4M%2Fl7K03mEQicD3r7f6AiAjQFKaXlXuG5LnrBihI4MwoAEcS2sIgYKfVlJREY%2B2Jyr%2FAwg6EAAaDDYzNzQyMzE4MzgwNSIMYoFOxH2r2kde8YiLKtwD%2F%2F4HaDyhrPqNA3Kq0QmiwbEaYfKT9%2B6bly8efH6eSJunpgt81MhDnjJku8tFJW8M4qJkyfq081GRknonR5m6ZNb1PuVFr%2FMxXP%2BupJPegzs2WBkyjytZEuFFo56qJL%2BANql%2BJllnN%2B4EyDLWPJYML5wfgAhZt7RYRxhkNJ7gUPNsP4B5QvO3zBxoG6Gd%2FhuHtnU9skq26%2FtEKKTl3zKJ7skt0tI6xgmH7QOAvaIgc0S6Vyy6zvttFxY2nMgmAsF0%2BJTEMUWCQRTcB1Vl62iD%2FfPeV0OSDJFURitqUwvPOR8OBw4tdfdnY%2B%2BF0U4Yp8CrgCLEC%2BONQ6IYN1mQQ31a9qXVKXdW3ERguuOzDcEVDyxxNycVn9j%2FTiYosZq2MxUkUtA4G%2FoN5EV70YA3m6j51Usb1GsJ%2BCrcg5Mw69huW5NokR1cp%2F8vdCxain5bC0x1bIh0hiEAWN9XxEeOmIcgEd%2FRrdVkAj2tY%2BpzpkRBeMhRUCo4CgdqeP4u4UDLO6kW5g6aHN0rskz5S7Hp%2BxrnY8TTbC0K%2FJupfdR2lEOzEuDV305z7bHLcfiVPRuVD%2BHvMDHewgDK2aqdhaL974R%2BnGYhlZwOSMP%2FpXO%2Bgz9kcne8%2BJ%2FYp6BnkU3kAiUwnc3B1AY6pgFpq%2FNlUOFTIAnT8fdGRQ9qq3DecLsCwgJMCEUZ39Faztq5YP%2BDL3%2B19kOY%2Fb%2FEiR0uBLYHKFiUCcw3to3mPwjFgWDO1zXCJzk3JWuMemV8oZDX6J9IYSW2Aq3b80jd8Wdl4gfmMV4zwfbCJ5%2FtYOwgY0B%2FuRLo%2BQKDx1nTebRWoMCm1a6yNUbJAVsT%2Bo3iwjvnN6Kcij8UXfMIli9DryNfyn9%2BQv1i&X-Amz-Signature=5ae0c8487b3f8b0cd8f64e1df79ea9659d965751ba9acc06f07d0faa96f5bf34&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) 我们再写几个类似的函数 ```haskell ifEvenDouble n = if even n then n * 2 else n

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)