This problem came up when I was trying to zip through lists of different length and I didn’t want them to be cut by the shortest one. It was in a context where the list had integers that I wanted to add or multiply. My problem is how to set up the type variables so that it can be more general.
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
Currently, because the element to pad the lists with has to be speficied, I have to write them this way, but it begs the question of whether it needs to be custom made for each context, or simply repurposed with higher order functions. Here’s one example of when such thing happens:
transposeWith :: a -> [[a]] -> [[a]]
transposeWith _ [xs] = [[x] | x <- xs]
transposeWith l (xs:xss) = zipPadWith l (++) xs (transposeWith l xss)
where
zipPadWith l f [] a = [f [l] m | m <- a]
zipPadWith l f a [] = [f m [l] | m <- [a]]
zipPadWith l f (x:xs) (ys:yss) = f [x] ys : zipPadWith l f xs yss
It transposes the list of lists in a rectangular fashion. Edit: I need to correct this last example. Give me some time please.
2