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
{- | Zip two lists which must be of the same length.
This is checked only lazily, that is unequal lengths are detected only
if the list is evaluated completely.
But it is more strict than @zipWithPad undefined f@
since the latter one may succeed on unequal length list if @f@ is lazy. -}
zipWithMatch
:: (a -> b -> c) {-^ function applied to corresponding elements of the lists -}
-> [a]
-> [b]
-> [c]
zipWithMatch f =
let aux (x:xs) (y:ys) = f x y : aux xs ys
aux [] [] = []
aux _ _ = error "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])