模式匹配Haskell中的多个元素

时间:2018-04-19 14:38:25

标签: haskell pattern-matching

如果我有一个类型列表:

[Circle r, Square s, Rectangle w d, Equil.Triangle t, Circle r, Rectangle wd]

我想在列表中交换两个相同类型的元素。 我尝试过例如模式匹配:

swap (Circle r1:y:Circle r2:xs) = (Circle r2:y:Circle r1:xs)

有没有办法将一个或多个元素与 y 匹配,还是有其他首选方法?

提前致谢!

2 个答案:

答案 0 :(得分:2)

我会使用split包,使用Circle s作为分隔符。有两个有趣的情况:列表以Circle开头,在这种情况下,前两个分隔符将位于拆分中前两个列表的开头,或者列表不以{{1开头在这种情况下,前两个分隔符将位于分割中第二个和第三个元素的开头。

Circle

答案 1 :(得分:2)

Per Daniel Wagner评论他的回答:

  

如果我想将第一个元素与具有相同构造函数的下一个元素交换,我会做一些不同的事情

我认为我也回答了这个问题,因为在这方面发布的问题含糊不清。我编写了一个通过构造函数测试相等性的函数,例如:

-- from your code somewhere, however this is defined
data Shape a = Circle a
             | Square a
             | Rectangle a a
             | EquilTriangle a

sameShape :: Shape a -> Shape a -> Bool
sameShape (Circle _) (Circle _)               = True
sameShape (Square _) (Square _)               = True
sameShape (Rectangle _ _) (Rectangle _ _)     = True
sameShape (EquilTriangle _) (EquilTriangle _) = True
sameShape _ _                                 = False

然后在x上以breaksameShape x拉出列表的头部,并从那里重新组合列表。

swapHeadWithSameConstructor :: [Shape a] -> [Shape a]
swapHeadWithSameConstructor xss@(x:xs) =
  let (xs', ys) = break (sameShape x) xs
  in  case ys of
        (y:ys') -> y : xs' ++ x : ys'
        []      -> xss  -- if there's no element to swap, change nothing