A search partitionMon Hayoo will return at least 2 libraries implementing this function. This means that you can either depend on them or study their source.
Here's a more readable translation of this implementation :
partitionM :: (Monad m) => (a -> m Bool) -> [a] -> m ([a], [a])
partitionM p xs = foldM f ([], []) xs
where
f (a, b) x = do
flag <- p x
return $ if flag
then (x : a, b)
else (a, x : b)
As for your question on how to raise a function partitionto partitionM, I came up with the following implementation of a lift function:
liftSplitter :: (Monad m) =>
((a -> Bool) -> [a] -> ([a], [a])) ->
(a -> m Bool) -> [a] -> m ([a], [a])
liftSplitter splitter kleisliPredicate list = do
predicateResultsAndItems <- sequence $ do
item <- list
return $ do
predicateResult <- kleisliPredicate item
return (predicateResult, item)
return $ results $ predicateResultsAndItems
where
results [] = ([], [])
results ((predicateResult, item) : tail) = (a ++ tailA, b ++ tailB)
where
(a, b) = splitter (const predicateResult) [item]
(tailA, tailB) = results tail
(a -> Bool) -> [a] -> ([a], [a])
(.. partition, break span)
(a -> m Bool) -> [a] -> m ([a], [a])