partitionR :: (a -> Bool) -> [a] -> ([a], [a], ([b] -> [b] -> [b])) partitionR _ [] = ([], [], \_ _ -> []) partitionR p (x:xs) | p x = (x:ts, fs, \(x:ts) fs -> x:rep ts fs) | otherwise = (ts, x:fs, \ts (x:fs) -> x:rep ts fs) where (ts, fs, rep) = partitionR p xs onPartitions :: (Monad m) => (a -> Bool) -> ([a] -> m [b]) -> ([a] -> m [b]) -> [a] -> m [b] onPartitions p t f xs = let (pt, pf, repartition) = partitionR p xs in repartition <$> t pt <*> f pf main :: IO () main = do onPartitions even (traverse print) (traverse print) [1..10] pure ()