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

how to transform a IO [FilePath] into a [FilePath]?

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

我的策略(如下所示)是将文件路径作为 IO [FilePath]。我想我可以解除 IO 以便可以过滤字符串元素。

我的想法有什么问题吗?我想知道我在 IO [FilePath] 上使用 liftIO 而不是 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

你不想在这里使用 liftIO,那是为了将 IO 动作提升到更复杂的 monad,而不是从 IO 动作中提取值。总之,不能把IO a变成aIO 的全部意义在于 防止 你这样做。不过,您可以使用 do 符号直接使用 a 值:

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.

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

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

上面的 fmap 将纯函数(如 filter ...)应用于某些 IO 值。请注意,结果类型仍将是 IO —— 同样,您永远无法逃脱 IO monad。