像这样设置zipWithPadding会有什么损失?(在Haskell中替换zipWith)

xnifntxz  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(105)

这个问题出现在我尝试压缩不同长度的列表时,我不想让它们被最短的一个截断。这是在一个上下文中,列表中有整数,我想相加或相乘。我的问题是如何设置类型变量,使它可以更通用。

zipWithPadding :: a -> (a -> a -> a) -> [a] -> [a] -> [a]
zipWithPadding n f = go n f
  where
    go n f [] a  = [f n x | x <- a]
    go n f a []  = [f n x | x <- a]
    go n f (x:xs) (y:ys) = f x y : go n f xs ys

目前,因为填充列表的元素必须被指定,所以我不得不这样写,但它回避了一个问题,即它是否需要为每个上下文定制,或者只是用更高阶的函数重新使用。
编辑:我想感谢评论中的Chris的帮助。它通过将上面的解决方案更改为以下内容,使底部的示例成为可能:

zipPadWith :: a -> b -> (a -> b -> c) -> [a] -> [b] -> [c]
zipPadWith n m f = go n m f
  where
    go n _ f [] a          = [f n x | x <- a]
    go _ m f a []          = [f x m | x <- a]
    go n m f (x:xs) (y:ys) = f x y : go n m f xs ys

例如:

transposeWith :: a -> [[a]] -> [[a]]
transposeWith n []       = []
transposeWith n (ms:mss) = zipPadWith n [] (:) ms (transposeWith n mss)

它转置列表的列表而不剪切内容。

k10s72fa

k10s72fa1#

如果我们以下面的方式实现zipPadWith,则将默认值作为两个参数应用于f会将签名约束为a -> (a -> a -> a) -> [a] -> [a] -> [a]

zipPadWith _ _ [] [] = []
zipPadWith n f (x:xs) (y:ys) = f x y : zipPadWith n f xs ys
zipPadWith n f (x:xs) [] = f x n : zipPadWith n f xs []
zipPadWith n f [] (y:ys) = f n y : zipPadWith n f [] ys

但是,如果该函数采用 * 两个 * 默认参数,一个用于左侧列表福尔斯时,另一个用于右侧列表不足时,则该类型不受约束,可以是a -> b -> (a -> b -> c) -> [a] -> [b] -> [c]

zipPadWith _ _ _ [] [] = []
zipPadWith n1 n2 f (x:xs) (y:ys) = f x y : zipPadWith n1 n2 f xs ys
zipPadWith n1 n2 f (x:xs) [] = f x n2 : zipPadWith n1 n2 f xs []
zipPadWith n1 n2 f [] (y:ys) = f n1 y : zipPadWith n1 n2 f [] ys

相关问题