2013-03-05 15 views
5

Mam następujący kod:Czy partycję można zastosować do `a -> IO Bool`?

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) 

Chciałbym napisać coś takiego jak return $ partitionM doesFileExist filtered. Czy istnieje sposób na ponowne użycie lub podniesienie numeru partition lub podwójne użycie numeru filterM w najlepszy sposób?

+1

Zakładasz każdy element 'filtered' jest albo plikiem lub katalogiem. To niekoniecznie jest prawdą. – melpomene

+1

http://www.haskell.org/pipermail/beginners/2009-December/002882.html. To może pomóc. –

+0

@melpomene, tak, to mi się nie przydarzyło (mam tylko pliki i katalogi w lokalizacjach, na które patrzę). W porządku, ale jestem bardziej ciekawy ogólnego przypadku, niekoniecznie dla funkcji System.Directory. @Dave, nie jestem jedynym, który się wtedy zastanawia :). Nie mogę uwierzyć, że wyszukiwarka google nie zwróciła tego podczas wyszukiwania na 'partitionM'. Wygląda na to, że w bibliotece nie ma czegoś łatwego ... – huynhjl

Odpowiedz

4

Wyszukiwanie dla partitionM na Hayoo zwróci Ci co najmniej 2 biblioteki implementujące tę funkcję. Oznacza to, że możesz polegać na nich lub studiować ich źródło.

Oto tłumaczenie bardziej czytelne od 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) 

chodzi o Twoje pytanie, w jaki sposób podnieść funkcję partition do partitionM, wpadłem na następujący realizacji funkcji podnoszenia:

Ta funkcja umożliwia podniesienie wszystkich funkcji typu
(a -> Bool) -> [a] -> ([a], [a]) 

(tj partition, break i span) do

(a -> m Bool) -> [a] -> m ([a], [a]) 
+0

Dziękuję. Nie wiedziałem o Hayoo, zaznaczam to jako zaakceptowane. Mogę zmienić swoją odpowiedź, jeśli komuś uda się podnieść partycję (w przeciwieństwie do pisania nowej funkcji partitionM) lub wyjaśnić, dlaczego nie jest to możliwe. – huynhjl

+0

@huynhjl Jest to możliwe, ale jest zbyt wyspecjalizowane i zasadniczo będzie wymagało skomponowania funkcji podnoszenia następującego podpisu typu: '((a -> Bool) -> [a] -> ([a], [a])) -> ((a -> m Bool) -> [a] -> m ([a], [a])) ", co nie będzie łatwe. Jako taka funkcja ta będzie miała zastosowanie tylko do 'partycji'. Z tego powodu rozsądniej jest zaimplementować 'partitionM'. –

+0

Dlaczego miałoby to zastosowanie tylko do partycji, a nie do czegoś, co zwraca '([a], [a])', takie jak 'span',' splitAt', 'break'? – huynhjl

Powiązane problemy