Haskell 分区可以应用于'a->;我爱你吗?
我有以下代码:Haskell 分区可以应用于'a->;我爱你吗?,haskell,monads,Haskell,Monads,我有以下代码: import System.Directory import System.FilePath import Control.Monad (filterM) filesAndDirs dir = do entries <- getDirectoryContents dir let filtered = [dir </> e | e <- entries, e `notElem` [".", ".."]] files <- filterM
import System.Directory
import System.FilePath
import Control.Monad (filterM)
filesAndDirs dir = do
entries <- getDirectoryContents dir
let filtered = [dir </> e | e <- entries, e `notElem` [".", ".."]]
files <- filterM doesFileExist filtered
dirs <- filterM doesDirectoryExist filtered
return (files, dirs)
导入系统目录
导入System.FilePath
导入控制.Monad(filterM)
filesAndDirs dir=do
条目搜索上的partitionM
将返回至少两个实现该功能的库。这意味着您可以依赖它们,也可以研究它们的来源
以下是更具可读性的翻译:
您可以使用此功能提升类型的所有功能
(a -> Bool) -> [a] -> ([a], [a])
(即,分区
,中断
和span
)到
假设筛选的的每个元素都是文件或目录。这不一定是真的。。这可能会有帮助。@melpomene,是的,我没有想到(我只是在查看的位置上有文件和目录)。虽然我对一般情况更感兴趣,但这很好,不一定是System.Directory函数@戴夫,我不是唯一一个想知道的人:)。我不敢相信谷歌搜索在partitionM
上搜索时没有返回这个。图书馆里似乎没有现成的东西……试着用引号搜索“partitionM”。谢谢。我不知道Hayoo的事我把这个标记为已接受。如果有人设法提升分区(而不是编写一个新的partitionM函数),我可能会更改我的答案,或者解释为什么它不可能。@huynhjl这是可能的,但它太专业化了,本质上需要您编写以下类型签名的提升函数:((a->Bool)->[a]->([a],[a])->((a->m Bool)->[a]->m([a],[a])
,这并不容易。因此,此功能仅适用于分区
。正因为如此,只实现partitionM
要明智得多。为什么它只适用于分区,而不适用于返回([a],[a])
的任何内容,例如span
,splitAt
,break
?@huynhjlsplitAt
具有不同的签名。关于span
和break
您是对的,这个提升功能也适用于他们,但就是这样,没有更多的功能了。@huynhjl查看更新。我已经实现了你想要的提升功能。对挑战感兴趣)
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])
(a -> m Bool) -> [a] -> m ([a], [a])