如何将IO [FilePath]转换为[FilePath]?

时间:2015-05-08 16:09:30

标签: haskell monads

我想查看当前目录,只打印.zip个文件。

我的策略(如下所示)是将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

2 个答案:

答案 0 :(得分:6)

您不想在此使用liftIO,这是为了将IO操作提升到更复杂的monad,而不是用于从IO操作中提取值。简而言之,您无法将IO a变为aIO的重点是阻止你这样做。不过,您可以使用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

答案 1 :(得分:3)

您无法从IO中提取任何内容,但您可以调整其他功能以处理IO

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

以上fmap将纯函数(filter ...)应用于某个IO值。请注意,结果类型仍为IO - 再次,您永远无法逃脱IO monad。