0

我正在尝试编写一个函数,它将两个数组的所有元素相加并返回一个数组。它输入两个列表。

addTogether :: Num t => ([t],[t]) -> [t]
addTogether (x, y) = mapM_ (\ (a, b) -> a + b) (zip x y)
4

2 回答 2

8

我认为你在这里采取了错误的方法。在编译器停止对你大喊大叫之前,你不会addTogether通过组合你模糊理解的函数来获得可靠的函数。这有点危险,Haskell 和 C 都是如此。要么你不使用这些函数,要么你彻底阅读了他们的文档、示例和理想情况下的代码。这是我的意见。

关于addTogether,有很多不同的实现方式。如果您花了一个小时尝试使用zip并且map没有任何令人满意的结果,那么您可能会尝试其他方法。例如,如果这是你的事,你可以用递归的方式处理它:

addTogether :: Num t => ([t], [t]) -> [t] 
addTogether ([],_) = []
addTogether (_,[]) = []
addTogether ((x:xs),(y:ys)) = (x + y):addTogether (xs,ys)

这里没有歧义。您也可以尝试使用列表推导(您想生成一个列表吗?),可能如下所示:

addTogether :: Num t => ([t],[t]) -> [t] 
addTogether (x, y)
    | null x || null y = []
    | otherwise = [ a + b | n <- [0..min (length x) (length y) - 1],
                            let a = x!!n,
                            let b = y!!n]

(它不处理无限列表,我很快就做到了)

@Daniel Fischer 解决方案非常好,但uncurry一开始可能有点令人不安。你可以这样看:

addTogether :: Num t => ([t],[t]) -> [t] 
addTogether (x, y) = zipWith (+) x y

我希望它对我糟糕的英语有所帮助和抱歉。

于 2012-10-03T04:18:29.353 回答
7

您应该在那里使用的功能是

map :: (a -> b) -> [a] -> [b]

但更好的选择是

addTogether :: Num t => ([t], [t]) -> [t]
addTogether = uncurry (zipWith (+))

的类型mapM_

mapM_ :: Monad m => (a -> m b) -> [a] -> m ()

这显然不符合您的预期目的。

于 2012-10-03T01:19:14.100 回答