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

时间:2012-03-21 21:10:18

标签: 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 middle ++ first

那么有没有办法在haskell中定义具有firstlast元素的模式结构,以及middle中的所有元素?

4 个答案:

答案 0 :(得分:6)

不,你不能。为什么?因为模式匹配匹配值及其子部分,但列表的“中间”不是列表的子部分。根据其结构,列表[1, 2, 3, 4]1:(2:(3:(4:[])))。因此,您希望将first1last匹配为4,这两者都是列表的子部分,因此不会被取消资格。但是你想要的middle2:(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

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