返回文章列表

文章

Get Programming with Haskell-6

对于 Haskell(以及一般的函数式编程),基本数据结构是一个列表

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

目录
  1. 3、列表中的通用函数
  2. 1. 基础操作
  3. 2. 元素处理
  4. 3. 高阶函数
  5. 4. 特殊构造
  6. 5、zip 和 zipWith 的独特价值
  7. -- 安全处理不等长列表 names = ["Alice", "Bob"] ages = [25, 30, 35] ghci> zip names ages -- 自动截断 [("Alice",25), ("Bob",30)] 2. **数学运算**: haskell -- 向量点积 dotProduct xs ys = sum (zipWith (*) xs ys) 3. **惰性求值**:支持无限列表: haskell ghci> take 3 (zip [1..] ["a","b","c","d"]) [(1,"a"), (2,"b"), (3,"c")] ```
  8. 为何重要?
  9. 📎 参考文章
# Lists 列表(list)是函数式编程中**最重要的数据结构**,其核心优势在于它天生具有递归性。一个列表要么是空列表(**`[]`**),要么是一个元素后接另一个列表(**`元素 : 列表`**)。对列表的**拆解**和**构建**是函数式编程众多技术的基石。 拆解列表时,主要关注三个部分: - **头部(head)**:列表的第一个元素 - **尾部(tail)**:除头部外的剩余部分(仍是一个列表) - **末端(****`[]`****)**:空列表,表示递归终止条件 ## 1、列表的结构解析 ### 1、分解列表 列表由head和tail两部分组成 ![](https://prod-files-secure.s3.us-west-2.amazonaws.com/4b1b167f-4b52-4031-8233-f4f2689af574/d362c6fc-3273-4f4b-b601-cd9db11ec909/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466VYRKTY3L%2F20260827%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260827T180948Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEHEaCXVzLXdlc3QtMiJHMEUCIBRta7zZPU6KXGYB7IAxPAkPVYm7ShdLD60jgwdUxbxaAiEAwfa2FN9jFtWqVybwPsjyZLcjUk7sMhhq6M7tTbaG%2FQYq%2FwMIOhAAGgw2Mzc0MjMxODM4MDUiDB1BayU3k4HvVoeitircA1iydYPtmGE4lmLnLRRa3srSBjBXuEi7UfF5kCjZBK7InPWaFLZmnqEs5S14WZ%2FK0RO87bqh5V6rM4nUIUek7JMdQToCMkG0UK7jcqu%2FlM%2B8JXvzycm5tfbIVm%2F0Sfqyvm7TA1Rl1x91DLCRBRgKRQ4bdvR28kYUQ%2FfyBgPIKx3wV14c2WlMUxxMtCRsCislKrM5rw49FxO5w0VPFRUl4xBpggFsautKrOrt%2F1%2Fx04yUHz%2BPsP5emiVVHJ3UQq6dQ74I7vpMiyu0bsUBzIwOJ9z0QhphrCQch47fCc2ypK2FXTx5b25zwr7hWAd6%2FQNIi2wyUrgxO%2FExTsQtMwADPqc%2F9D%2B7jEW%2BLv98y87h8XVl9hvDreHnFkhVJDa4JuY1Nm4e12aJ2Vq3RCmkq0k%2BfGKng%2By7joZS%2F7jg%2FIeyGF52i6wz0a0wZDaML%2Fvr8X66%2Bcyzeb1ZWk%2BRRhaW5SkrwjSSpxtUCi50r%2B1rz8JGk717LN3l1i6B9id1C5Nn8Tz2AzIio2TN0L4%2FGpaDUXTEDLqCxby4CXkBFNhVi%2FUvH0hHvrZypvQbNc1jXieqMPmLbYIeqeJi8d8duy3zXGtePzNDPN13gCrpOxHM%2FfQu73Uij3dE8rPT4wSfWB3RMIfOwdQGOqUBcLL787qfJkC6LGh4VKik%2FbeSr9iiXD%2FESiJu35a6Y1Mvl6pJ6zwTiBZcxbFQfL%2FyTyJiIMx5YFNykV85iavlctsGJEPODQjjTZvBmO29WljCJYCJT1d0oWbpyHfuOGl1AdAA5A3dW0oHWxUsOExD%2FYKnVbayFJIdBHYxiA7prpjwbJwJklXU5PR2ybZ1VVkAjKccUaz5kOlvB7mqx78s9qmZVr%2FE&X-Amz-Signature=01359b09fa1609a4777502746ae69e4065b522a800efa4e8b293313d6fde8dca&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) `head` 函数是返回列表的第一个元素,`tail`是返回第一个元素后面的所有元素,如果列表只有一个元素,`tail`则返回空列表`[]`. ### 2、构造列表 构造列表我们需要使用`:` 操作符,这个操作符叫做`cons` ,来源于**Lisp**中的*construct*的缩写,在 Haskell 中,所有列表在底层均由一系列的 **`cons`**** 操作**(即 **`:`** 运算符)构成,而方括号 **`[...]`** 的表示法仅仅是语法糖(一种旨在提升代码可读性的语法特性)。
![](https://prod-files-secure.s3.us-west-2.amazonaws.com/4b1b167f-4b52-4031-8233-f4f2689af574/20b69ab6-6639-4cf3-8230-2803be233346/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466VYRKTY3L%2F20260827%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260827T180948Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEHEaCXVzLXdlc3QtMiJHMEUCIBRta7zZPU6KXGYB7IAxPAkPVYm7ShdLD60jgwdUxbxaAiEAwfa2FN9jFtWqVybwPsjyZLcjUk7sMhhq6M7tTbaG%2FQYq%2FwMIOhAAGgw2Mzc0MjMxODM4MDUiDB1BayU3k4HvVoeitircA1iydYPtmGE4lmLnLRRa3srSBjBXuEi7UfF5kCjZBK7InPWaFLZmnqEs5S14WZ%2FK0RO87bqh5V6rM4nUIUek7JMdQToCMkG0UK7jcqu%2FlM%2B8JXvzycm5tfbIVm%2F0Sfqyvm7TA1Rl1x91DLCRBRgKRQ4bdvR28kYUQ%2FfyBgPIKx3wV14c2WlMUxxMtCRsCislKrM5rw49FxO5w0VPFRUl4xBpggFsautKrOrt%2F1%2Fx04yUHz%2BPsP5emiVVHJ3UQq6dQ74I7vpMiyu0bsUBzIwOJ9z0QhphrCQch47fCc2ypK2FXTx5b25zwr7hWAd6%2FQNIi2wyUrgxO%2FExTsQtMwADPqc%2F9D%2B7jEW%2BLv98y87h8XVl9hvDreHnFkhVJDa4JuY1Nm4e12aJ2Vq3RCmkq0k%2BfGKng%2By7joZS%2F7jg%2FIeyGF52i6wz0a0wZDaML%2Fvr8X66%2Bcyzeb1ZWk%2BRRhaW5SkrwjSSpxtUCi50r%2B1rz8JGk717LN3l1i6B9id1C5Nn8Tz2AzIio2TN0L4%2FGpaDUXTEDLqCxby4CXkBFNhVi%2FUvH0hHvrZypvQbNc1jXieqMPmLbYIeqeJi8d8duy3zXGtePzNDPN13gCrpOxHM%2FfQu73Uij3dE8rPT4wSfWB3RMIfOwdQGOqUBcLL787qfJkC6LGh4VKik%2FbeSr9iiXD%2FESiJu35a6Y1Mvl6pJ6zwTiBZcxbFQfL%2FyTyJiIMx5YFNykV85iavlctsGJEPODQjjTZvBmO29WljCJYCJT1d0oWbpyHfuOGl1AdAA5A3dW0oHWxUsOExD%2FYKnVbayFJIdBHYxiA7prpjwbJwJklXU5PR2ybZ1VVkAjKccUaz5kOlvB7mqx78s9qmZVr%2FE&X-Amz-Signature=d7513cee5540f4e33c29f7418ec7faf92351c7295a9481dc8b2376454f508f71&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) 值得注意的是,目前你所见到的**字符串**本质上也是语法糖——它们实际上是**字符列表**(用双引号 **`" "`** 表示,而非单引号 **`' '`** 包裹的单个字符)
![](https://prod-files-secure.s3.us-west-2.amazonaws.com/4b1b167f-4b52-4031-8233-f4f2689af574/91af5c1a-6dce-4249-a374-08d9bee62d83/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466VYRKTY3L%2F20260827%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260827T180948Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEHEaCXVzLXdlc3QtMiJHMEUCIBRta7zZPU6KXGYB7IAxPAkPVYm7ShdLD60jgwdUxbxaAiEAwfa2FN9jFtWqVybwPsjyZLcjUk7sMhhq6M7tTbaG%2FQYq%2FwMIOhAAGgw2Mzc0MjMxODM4MDUiDB1BayU3k4HvVoeitircA1iydYPtmGE4lmLnLRRa3srSBjBXuEi7UfF5kCjZBK7InPWaFLZmnqEs5S14WZ%2FK0RO87bqh5V6rM4nUIUek7JMdQToCMkG0UK7jcqu%2FlM%2B8JXvzycm5tfbIVm%2F0Sfqyvm7TA1Rl1x91DLCRBRgKRQ4bdvR28kYUQ%2FfyBgPIKx3wV14c2WlMUxxMtCRsCislKrM5rw49FxO5w0VPFRUl4xBpggFsautKrOrt%2F1%2Fx04yUHz%2BPsP5emiVVHJ3UQq6dQ74I7vpMiyu0bsUBzIwOJ9z0QhphrCQch47fCc2ypK2FXTx5b25zwr7hWAd6%2FQNIi2wyUrgxO%2FExTsQtMwADPqc%2F9D%2B7jEW%2BLv98y87h8XVl9hvDreHnFkhVJDa4JuY1Nm4e12aJ2Vq3RCmkq0k%2BfGKng%2By7joZS%2F7jg%2FIeyGF52i6wz0a0wZDaML%2Fvr8X66%2Bcyzeb1ZWk%2BRRhaW5SkrwjSSpxtUCi50r%2B1rz8JGk717LN3l1i6B9id1C5Nn8Tz2AzIio2TN0L4%2FGpaDUXTEDLqCxby4CXkBFNhVi%2FUvH0hHvrZypvQbNc1jXieqMPmLbYIeqeJi8d8duy3zXGtePzNDPN13gCrpOxHM%2FfQu73Uij3dE8rPT4wSfWB3RMIfOwdQGOqUBcLL787qfJkC6LGh4VKik%2FbeSr9iiXD%2FESiJu35a6Y1Mvl6pJ6zwTiBZcxbFQfL%2FyTyJiIMx5YFNykV85iavlctsGJEPODQjjTZvBmO29WljCJYCJT1d0oWbpyHfuOGl1AdAA5A3dW0oHWxUsOExD%2FYKnVbayFJIdBHYxiA7prpjwbJwJklXU5PR2ybZ1VVkAjKccUaz5kOlvB7mqx78s9qmZVr%2FE&X-Amz-Signature=289f90fb4e228155193df876a4b4f2a871d62358c0b00f7b73c2e37fbd0a8183&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) 需要牢记的是,在 Haskell 中,**列表的所有元素必须为同一类型**。例如,你可以将字符 **`'h'`** 通过 **`cons`** 操作(即 **`:`** 运算符)添加到字符串 **`"ello"`** 的开头,因为: - **`"ello"`** 本质上是一个字符列表(**`[Char]`**) - **`'h'`**(单引号包裹)是一个独立的 **`Char`** 类型字符 ```c++ Prelude> 'h':"ello" "hello" ``` 但你不能将 **`"h"`**(双引号)通过 **`cons`** 操作(**`:`**)拼接到 **`"ello"`** 前面,因为: - **`"h"`** 是一个**单元素的字符列表**(类型为 **`[Char]`**,等价于 **`['h']`**) - **`"ello"`** 中的元素是**独立的字符**(类型为 **`[Char]`**) **当去掉语法糖后,这一限制会变得更加直观**: ![](https://prod-files-secure.s3.us-west-2.amazonaws.com/4b1b167f-4b52-4031-8233-f4f2689af574/afa4b281-e4d2-4402-8f95-ad2f1a20e177/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466VYRKTY3L%2F20260827%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260827T180948Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEHEaCXVzLXdlc3QtMiJHMEUCIBRta7zZPU6KXGYB7IAxPAkPVYm7ShdLD60jgwdUxbxaAiEAwfa2FN9jFtWqVybwPsjyZLcjUk7sMhhq6M7tTbaG%2FQYq%2FwMIOhAAGgw2Mzc0MjMxODM4MDUiDB1BayU3k4HvVoeitircA1iydYPtmGE4lmLnLRRa3srSBjBXuEi7UfF5kCjZBK7InPWaFLZmnqEs5S14WZ%2FK0RO87bqh5V6rM4nUIUek7JMdQToCMkG0UK7jcqu%2FlM%2B8JXvzycm5tfbIVm%2F0Sfqyvm7TA1Rl1x91DLCRBRgKRQ4bdvR28kYUQ%2FfyBgPIKx3wV14c2WlMUxxMtCRsCislKrM5rw49FxO5w0VPFRUl4xBpggFsautKrOrt%2F1%2Fx04yUHz%2BPsP5emiVVHJ3UQq6dQ74I7vpMiyu0bsUBzIwOJ9z0QhphrCQch47fCc2ypK2FXTx5b25zwr7hWAd6%2FQNIi2wyUrgxO%2FExTsQtMwADPqc%2F9D%2B7jEW%2BLv98y87h8XVl9hvDreHnFkhVJDa4JuY1Nm4e12aJ2Vq3RCmkq0k%2BfGKng%2By7joZS%2F7jg%2FIeyGF52i6wz0a0wZDaML%2Fvr8X66%2Bcyzeb1ZWk%2BRRhaW5SkrwjSSpxtUCi50r%2B1rz8JGk717LN3l1i6B9id1C5Nn8Tz2AzIio2TN0L4%2FGpaDUXTEDLqCxby4CXkBFNhVi%2FUvH0hHvrZypvQbNc1jXieqMPmLbYIeqeJi8d8duy3zXGtePzNDPN13gCrpOxHM%2FfQu73Uij3dE8rPT4wSfWB3RMIfOwdQGOqUBcLL787qfJkC6LGh4VKik%2FbeSr9iiXD%2FESiJu35a6Y1Mvl6pJ6zwTiBZcxbFQfL%2FyTyJiIMx5YFNykV85iavlctsGJEPODQjjTZvBmO29WljCJYCJT1d0oWbpyHfuOGl1AdAA5A3dW0oHWxUsOExD%2FYKnVbayFJIdBHYxiA7prpjwbJwJklXU5PR2ybZ1VVkAjKccUaz5kOlvB7mqx78s9qmZVr%2FE&X-Amz-Signature=f9ac780f4c70a0d4c97f49df984f5a4138928a7af2667d65e10a53c386badc93&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)