我正在尝试编写一个Haskell函数,它将获取三个列表并返回其元素总和的列表.目前我正在尝试使用zipWith3:
sum3 :: Num a => [a] -> [a] -> [a] -> [a]
sum3 xs ys zs  = zipWith3 (\x y z -> x+y+z) xs ys zs 
问题是它只适用于相同长度的列表.但我希望sum3使用不等长的列表,以便这样做
sum3 [1,2,3] [4,5] [6]
会回来的
[11,7,3]
我认为我应该重新定义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]
因为很明显,要总结列 ;)
> sum3 [1,2,3] [4,5] [6]
[11,7,3]
我以前见过这样的问题,这里: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
现在我们可以用适当的填充来打包数字列表
pad0 :: [Int] -> Padme Int
pad0 = (:- 0)
这给了
padded ((\x y z -> x+y+z) <$> pad0 [1,2,3] <*> pad0 [4,5] <*> pad0 [6])
= [11,7,3]
或者,如果没有可用的成语括号,你可以写
padded (|pad0 [1,2,3] + (|pad0 [4,5] + pad0 6|)|)
意思是一样的.
Applicative 为您提供了一个很好的方法来解决这个问题所要求的"填充"的基本思想.