这个问题出现在我尝试压缩不同长度的列表时,我不想让它们被最短的一个截断。这是在一个上下文中,列表中有整数,我想相加或相乘。我的问题是如何设置类型变量,使它可以更通用。
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)
它转置列表的列表而不剪切内容。
1条答案
按热度按时间k10s72fa1#
如果我们以下面的方式实现
zipPadWith
,则将默认值作为两个参数应用于f
会将签名约束为a -> (a -> a -> a) -> [a] -> [a] -> [a]
。但是,如果该函数采用 * 两个 * 默认参数,一个用于左侧列表福尔斯时,另一个用于右侧列表不足时,则该类型不受约束,可以是
a -> b -> (a -> b -> c) -> [a] -> [b] -> [c]
。