Haskell模式匹配第一部分、中间部分和最后一部分

Haskell模式匹配第一部分、中间部分和最后一部分,haskell,recursion,pattern-matching,Haskell,Recursion,Pattern Matching,所以我想在Haskell中做一个简单的字符串反转函数 swapReverse :: String => String swapReverse [x] = [x] swapReverse [x,y] = [y,x] swapReverse (x:xs:l) = -- pattern match fails here let last = [l] middle = xs first = [x] in last ++ swapReverse

所以我想在Haskell中做一个简单的字符串反转函数

swapReverse :: String => String  
swapReverse [x] = [x]
swapReverse [x,y] = [y,x]
swapReverse (x:xs:l) =         -- pattern match fails here 
  let last = [l]
      middle = xs
      first = [x]
  in  last ++ swapReverse middle ++ first

那么,有没有一种方法可以在haskell中定义一个模式结构,它有
first
last
元素,并且
中间的所有元素都有
呢?

模式匹配在构造函数上起作用,是唯一的列表构造函数,因此不能在列表中间进行匹配。您需要向后构造新列表(显然:),这可以通过取列表的头部并将其附加到列表其余部分的背面来完成。

不,您不能。为什么?因为模式匹配匹配值及其子部分,但列表的“中间”不是列表的子部分。列表
[1,2,3,4]
就其结构而言是
1:(2:(3:[]))
。因此,您希望将
first
1
last
4
相匹配,这两个部分都是列表的子部分,因此不会被取消资格。但是您想要的中间部分是
2:[])
,它不是列表的子部分,因此不能匹配

请注意,我们也不能同时编写模式来匹配列表的第一个和最后一个元素。模式的深度在编译时是固定的。

请尝试以下代码:

last1 (x:xs:l) = (x,xs,l)
l
不会得到列表中的最后一个元素,而是得到列表中除前两个变量外的其余部分,前两个变量分配给列表中的前两个元素

当您为列表编写模式匹配时,第一个变量被分配给第一个元素,依此类推,直到程序得到最后一个变量,剩下的所有内容都被分配给它。在
x
之后添加
s
没有什么特别之处,名为
y
的变量也会做同样的事情

如果要获取列表的最后一个元素,需要创建一个类似于
(x:xs)
的模式,并在
xs
上使用递归并应用该模式,直到找到一个列表元素,这是最后一个元素。但是,我建议阅读答案,以找到一种更好的方法来反转列表,该方法不涉及查找列表的第一个和最后一个元素。

工作版本:

swapReverse :: String -> String  
swapReverse (x:xs) = [last xs] ++ swapReverse (init xs) ++ [x]
swapReverse xs = xs

请注意,此实现在性能方面是一场灾难。使用折叠和/或累加器的实现效率更高。

我只想指出,第三种模式,
(x:xs:l)
实际上可以匹配,但不是您所期望的。它将
x
与第一个元素相匹配,
xs
与第二个元素相匹配,
l
与列表的其余部分相匹配。注意类型声明:)您可能指的是
swapReverse::String->String
,或者更一般的东西,如
swapReverse::[a]->[a]
。顺便说一句,查找链表的最后一个元素是O(N)。你几乎从来都不想这样做。类型签名必须是
String->String
,顺便说一句