Haskell模式匹配第一部分、中间部分和最后一部分
所以我想在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
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
,顺便说一句