所以我想在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
元素的模式结构,以及middle
中的所有元素?
答案 0 :(得分:6)
[1, 2, 3, 4]
为1:(2:(3:(4:[])))
。因此,您希望将first
与1
和last
匹配为4
,这两者都是列表的子部分,因此不会被取消资格。但是你想要的middle
是2:(3:[])
,它不是列表的子部分,因此不能匹配。
请注意,我们也无法编写模式以同时匹配列表的第一个和最后一个元素。模式的深度在编译时固定。
答案 1 :(得分:5)
模式匹配适用于构造函数, : 是唯一的列表构造函数,因此您无法在列表的中间进行匹配。你需要向后构建新的列表(显然:)),这可以通过取头并将其附加到列表其余部分的反向来完成。
答案 2 :(得分:1)
试试这段代码:
last1 (x:xs:l) = (x,xs,l)
l
没有得到列表中的最后一个元素,除了前两个变量之外,它还是列表的其余部分,它们被分配给列表中的前两个元素。
当您为列表编写模式匹配时,第一个变量将被赋予第一个元素,依此类推,直到程序到达最后一个变量,其中剩下的所有内容都分配给它。在s
之后添加x
没有什么特别之处,名为y
的变量会做同样的事情。
如果要获取列表的最后一个元素,则需要创建类似于(x:xs)
的模式,并在xs
上使用递归并应用该模式,直到找到一个列表元素,这是最后一个元素。但是,我建议阅读Adam Bergmark's答案,以便更好地反转不涉及查找列表的第一个和最后一个元素的列表。
答案 3 :(得分:0)
工作版本:
swapReverse :: String -> String
swapReverse (x:xs) = [last xs] ++ swapReverse (init xs) ++ [x]
swapReverse xs = xs
请注意,此实施在性能方面是灾难。使用折叠和/或累加器的实现效率更高。