首页 > 解决方案 > Haskell:为什么 (x:xs) 只匹配一个元素的列表?

问题描述

给定函数的这个定义f

f :: [Int] -> [Int]
f [] = []
f (x:xs) = x:[]

我会假设一个电话,如

f [1]

不会匹配,因为模式只匹配,如果列表中的后面(x:xs)有更多元素,而列表不是这种情况。或者是吗?xsx[1]

标签: listhaskell

解决方案


如果你写[x]一个包含一个元素的列表,这是 的缩写(x : []),甚至更详细(:) x []。所以它是一个(:)带有 as 元素的“cons”()x,而空列表作为尾部。

所以你的函数f (x:xs)确实会匹配一个包含一个(或多个)元素的列表。对于具有一个元素的列表,x将是元素和xs一个空列表。

不会匹配,因为模式只匹配,如果列表中的后面(x:xs)有更多元素,而列表不是这种情况。xsx[1]

(x:xs)匹配每个非空列表、列表x的第一个元素以及xs剩余元素的(可能为空的)列表。

如果您只想匹配包含两个或多个元素的列表。您可以将其与:

-- two or more elements
f (x1 : x2 : xs) = …

这里and将分别匹配列表的第一项和第二项,并且是一个包含剩余元素的列表。x1x2xs

编辑:回答您的意见

我想知道为什么我的函数定义首先会编译,因为函数类型是[Int] -> [Int],所以如果我给它一个空列表,那不是[Int]结果,是吗?

空列表[]是该[a]类型的数据构造函数之一,这意味着它[]具有 type [] :: [a]。它可以将类型变量a与匹配Int,因此[]可以具有类型[] :: [Int]

其次,如何匹配一个只有两个元素的列表?[a, b]?

您可以将此类列表与:

f (a : b : []) = …

或者您可以将其与:

f [a, b] = …

两者是等价的。[a, b]语法糖:它被编译器替换为(a : b : []),但是对于人类来说,使用它当然更方便[a, b]


推荐阅读