在Haskell中使用zipWith3的sum3

Chi*_*ffa 1 haskell

我正在尝试编写一个Haskell函数,它将获取三个列表并返回其元素总和的列表.目前我正在尝试使用zipWith3:

sum3 :: Num a => [a] -> [a] -> [a] -> [a]
sum3 xs ys zs  = zipWith3 (\x y z -> x+y+z) xs ys zs 
Run Code Online (Sandbox Code Playgroud)

问题是它只适用于相同长度的列表.但我希望sum3使用不等长的列表,以便这样做

sum3 [1,2,3] [4,5] [6]
Run Code Online (Sandbox Code Playgroud)

会回来的

[11,7,3]
Run Code Online (Sandbox Code Playgroud)

我认为我应该重新定义zipWith3来处理不等长的列表,但是无法弄清楚如何做(我怀疑我必须用尽所有空列表的可能性).有解决方案吗?

Car*_*ten 12

一个很好的技巧是使用 transpose:

import Data.List (transpose)

sum3 :: Num a => [a] -> [a] -> [a] -> [a]
sum3 as bs cs = map sum $ transpose [as,bs,cs]
Run Code Online (Sandbox Code Playgroud)

因为很明显,要总结 ;)


> sum3 [1,2,3] [4,5] [6]
[11,7,3]
Run Code Online (Sandbox Code Playgroud)


pig*_*ker 5

我以前见过这样的问题,这里:Zip默认值而不是丢值? 对这个问题的回答也属于这里.

ZipList具有指定填充元素的应用列表是适用的(应用从正数上的1和最大幺半群结构生长).

data Padme m = (:-) {padded :: [m], padder :: m} deriving (Show, Eq)

instance Applicative Padme where
  pure = ([] :-)
  (fs :- f) <*> (ss :- s) = zapp fs ss :- f s where
    zapp  []        ss        = map f ss
    zapp  fs        []        = map ($ s) fs
    zapp  (f : fs)  (s : ss)  = f s : zapp fs ss

-- and for those of you who don't have DefaultSuperclassInstances
instance Functor Padme where fmap = (<*>) . pure
Run Code Online (Sandbox Code Playgroud)

现在我们可以用适当的填充来打包数字列表

pad0 :: [Int] -> Padme Int
pad0 = (:- 0)
Run Code Online (Sandbox Code Playgroud)

这给了

padded ((\x y z -> x+y+z) <$> pad0 [1,2,3] <*> pad0 [4,5] <*> pad0 [6])
= [11,7,3]
Run Code Online (Sandbox Code Playgroud)

或者,如果没有可用的成语括号,你可以写

padded (|pad0 [1,2,3] + (|pad0 [4,5] + pad0 6|)|)
Run Code Online (Sandbox Code Playgroud)

意思是一样的.

Applicative 为您提供了一个很好的方法来解决这个问题所要求的"填充"的基本思想.

  • 有没有理由我们不能简单地写`(| pad0 [1,2,3] + pad0 [4,5] + pad0 [6] |)`(你错过了`[````````周围,BTW )?或者,更一般地说,我们可以将`(... ...)`里面的`(... ...)`视为`(| ... |)`? (2认同)
  • @ user3237465这是一个有争议的问题.简短而错误的答案是我从来没有为SHE解析器添加优先级/关联性处理.更好的答案是成语括号为您提供一个顶级应用程序.但可以说,他们应该申请一个完整的代码区域,只要有一个明确的方式来表明哪些子树已经恢复到"正常". (2认同)