我试图将两个列表放在一起,并保留未使用的额外元素,并将它们添加到新列表中。
addLists [1,2,3] [1,3,5,7,9] = [2,5,8,7,9]到目前为止,我有这样的看法:
addLists :: Num a => [a] -> [a] -> [a]
addLists xs ys = zipWith (+) xs ys但不知道如何将额外的元素放到新的列表中。
下一步是将其转换为一个高阶函数,该函数以组合函数为参数:
longZip :: (a -> a -> a) -> [a] -> [a] -> [a]发布于 2020-11-18 11:48:04
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]是实施为[src]
zipWith ::( a -> b->c ) ->a->b->c zipWith f= go [] go _ [] = [] go (x: xs ) (y: ys ) =f x y: go xs
因此,它使用显式递归,其中go将检查这两个列表是否为非空列表,在这种情况下生成f x y,否则它将停止并返回一个空列表[]。
您可以实现zipWith的一个变体,它将继续执行,即使其中一个列表是空的。THis的外观如下:
zipLongest :: (a -> a -> a) -> [a] -> [a] -> [a]
zipLongest f = go
where go [] ys = …
go xs [] = …
go (x:xs) (y:ys) = f x y : go xs ys你还需要填写…。
发布于 2020-11-18 15:09:23
你可以用更高级的函数来做,就像
import Data.List (transpose)
addLists :: Num a => [a] -> [a] -> [a]
addLists xs ys = map sum . transpose $ [xs, ys]因为transpose[xs, ys, ...]的长度是其参数列表中最长的列表的长度,而sum :: (Foldable t, Num a) => t a -> a已经定义为对列表的元素进行求和(因为列表是Foldable)。
transpose在这里被用作一种zip (但是删除最长而不是最短的列表),[]是列表添加++的默认元素,就像0是数字相加+的默认元素一样。
cutLongest [xs, ys] $
zipWith (++) (map pure xs ++ repeat []) (map pure ys ++ repeat [])另请参阅:
发布于 2020-11-18 17:55:35
你在找套餐。它给了你一个像拉链这样的操作,但这一直持续到两个列表都用完为止。它还泛化为列表以外的类型,如玫瑰树。在你的情况下,你会像这样使用它:
import Data.Semialign
import Data.These
addLists :: (Semialign f, Num a) => f a -> f a -> f a
addLists = alignWith (mergeThese (+))
longZip :: Semialign f => (a -> a -> a) -> f a -> f a -> f a
longZip = alignWith . mergeThese新类型签名是可选的。如果你想要,你可以继续使用你的旧的限制他们的列表。
https://stackoverflow.com/questions/64892335
复制相似问题