我如何将一个3-元组的列表转换成一个3-三元组的列表在Haskell?



我正在尝试编写一个函数,它接受一个三元组列表,并产生一个由三个列表组成的3元组。例如,在 [(a,b,c), (d, e, f), (g, h, i)]上调用的函数应该生成([a,d,g], [b, e, j], [c, f, i])

我到目前为止有这个:

-- This gives the head of a 3-tuple
fst3 :: (a, b, c) -> a
fst3 (x, _, _) = x
unzipTriples :: [(a, b, c)] -> a
unzipTriples (x : y : z : xs) = (fst3 x : fst3 y : fst3 z, unzipTriples xs)

我认为这将创建一个列表[a, d, g],然后将其添加到3元组中,并为剩余的列表执行其余操作。我该如何改进这个错误的函数?

unzipTriples (x : y : z : xs) = …中的模式(x : y : z : xs)将采用列表的前三个元素,因此x, yz是三元组。但是这样的话,您只能处理包含三个或更多元素的列表。

你能做的是使用map,从而使用:

fst3 :: (a, b, c) -> a
fst3 (a, _, _) = a
snd3 :: (a, b, c) -> b
snd3 (_, b, _) = b
thd3 :: (a, b, c) -> c
thd3 (_, _, c) = c
unzipTriples :: [(a, b, c)] -> ([a], [b], [c])
unzipTriples xs = (map fst3 xs, map snd3 xs, map thd3 xs)

但是它可能更优雅,并且当您对列表的第一项(一个3元组)进行模式匹配,然后对列表的尾部进行递归时,将消耗更少的内存,因此:

unzipTriples :: [(a, b, c)] -> ([a], [b], [c])
unzipTriples [] = ([], [], [])
unzipTriples ((a, b, c):xs) = (a:as, b:bs, c:cs)
    where ~(as, bs, cs) = unzipTriples xs

可以使用 foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b 将其转换为表达式,我把它作为练习。

最新更新