如果我有一个类型列表:
[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 匹配,还是有其他首选方法?
提前致谢!
答案 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
上以break
,sameShape 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