module NumericPrelude.List where import Data.List.HT (switchL, switchR, ) {- * Zip lists -} {- | zip two lists using an arbitrary function, the shorter list is padded -} {-# INLINE zipWithPad #-} zipWithPad :: a {-^ padding value -} -> (a -> a -> b) {-^ function applied to corresponding elements of the lists -} -> [a] -> [a] -> [b] zipWithPad z f = let aux l [] = map (\x -> f x z) l aux [] l = map (\y -> f z y) l aux (x:xs) (y:ys) = f x y : aux xs ys in aux {-# INLINE zipWithOverlap #-} zipWithOverlap :: (a -> c) -> (b -> c) -> (a -> b -> c) -> [a] -> [b] -> [c] zipWithOverlap fa fb fab = let aux (x:xs) (y:ys) = fab x y : aux xs ys aux xs [] = map fa xs aux [] ys = map fb ys in aux {- This is exported as Checked.zipWith. We need to define it here in order to prevent an import cycle. -} zipWithChecked :: (a -> b -> c) {-^ function applied to corresponding elements of the lists -} -> [a] -> [b] -> [c] zipWithChecked f = let aux (x:xs) (y:ys) = f x y : aux xs ys aux [] [] = [] aux _ _ = error "Checked.zipWith: lists must have the same length" in aux {- | Apply a function to the last element of a list. If the list is empty, nothing changes. -} {-# INLINE mapLast #-} mapLast :: (a -> a) -> [a] -> [a] mapLast f = switchL [] (\x xs -> uncurry (:) $ foldr (\x1 k x0 -> (x0, uncurry (:) (k x1))) (\x0 -> (f x0, [])) xs x) mapLast' :: (a -> a) -> [a] -> [a] mapLast' f = let recourse [] = [] -- behaviour as needed in powerBasis -- otherwise: error "mapLast: empty list" recourse (x:xs) = uncurry (:) $ if null xs then (f x, []) else (x, recourse xs) in recourse mapLast'' :: (a -> a) -> [a] -> [a] mapLast'' f = switchR [] (\xs x -> xs ++ [f x])