2015-05-08 2 views
0

Я хотел бы посмотреть в моем текущем каталоге и только распечатать .zip файлов.Как преобразовать IO [FilePath] в [FilePath]?

Моя стратегия (показано ниже) заключается в том, чтобы получить FilePaths как IO [FilePath]. Я думал, что смогу поднять IO, чтобы можно было фильтровать элементы строки.

Что не так в моих мыслях? Интересно, если это проблема, я использую liftIO на IO [FilePath] вместо IO FilePath.

import System.Directory 
import System.FilePath.Glob 
import Control.Monad.IO.Class 

main :: IO() 

listCompressedImages folder = 
    filter (match (compile ".zip")) (liftIO (getDirectoryContents folder)) 

main = listCompressedImages "." >>= print 
+0

* Никогда, никогда, никогда * используйте 'liftIO'! Если вы используете 'liftIO', вы практикуете ужасный Haskell. Я понимаю, что вы новичок, но вам нужно учиться! – AJFarmar

+7

@AJFarmar Что за черт? 'liftIO' очень полезен и, конечно, не ужасный Haskell. Это не обязательно полезно здесь, но ваш совет, чтобы избежать его любой ценой, кажется нецелесообразным. –

+0

У меня возникли проблемы с поиском канонического вопроса «IO a -> a'; но я нашел тот, который довольно близок. Если вы можете найти лучший, пожалуйста, пингуйте меня. –

ответ

3

Вы не можете ничего из IO извлечь, но вы можете адаптировать другие функции для работы на IO значений

listCompressedImages folder = 
    filter (match (compile ".zip")) `fmap` getDirectoryContents folder 

Приведенный выше fmap применяет чистую функцию (как filter ...) до некоторой IO значения. Обратите внимание, что результирующий тип все равно будет IO - снова вы никогда не сможете избежать монады IO.

6

Вы не хотите использовать liftIO здесь, это для подъема в IO действия к более сложной монаде, а не для извлечения значения из IO действия. Короче говоря, вы не можете превратить IO a в a. Вся цель IO - предотвратить вы от этого. Вы можете работать со значением a непосредственно с помощью do обозначения, хотя:

listCompressedImages :: FilePath -> IO [FilePath] 
listCompressedImages folder = do 
    -- getDirectoryContents :: FilePath -> IO [FilePath] 
    -- contents :: [FilePath] 
    contents <- getDirectoryContents folder 
    -- filter (match (compile ".zip")) :: [FilePath] -> [FilePath] 
    return $ filter (match (compile ".zip")) contents 

main :: IO() 
main = do 
    -- compressedImages :: [FilePath] 
    compresssedImages <- listCompressedImages "." 
    print compressedImages 

Всякий раз, когда у вас есть что-то с типом IO a, и вы хотите, чтобы получить значение типа a из него, используйте do обозначения и извлечь его с помощью <- , Для более подробного объяснения я отложил до Learn You a Haskell.

+0

спасибо. Наверное, мне это нужно в чайных ложках. Логика заключается в том, что фильтр применяет соответствие функции (с шаблоном) для каждого элемента содержимого, правильно? когда я добавляю t.zip-файл в свою папку, это все равно возвращает пустой список. – stian

+0

Я выяснил, что мне нужно было использовать (скомпилировать «* .zip») (подстановочный знак). – stian