Haskell-绑定映射的单子函数

时间:2019-05-03 00:08:12

标签: haskell io monads

在这里的这段代码中,我有一个函数tagsort,该函数使用FilePath并返回IO字符串。

   builddir xs = do
    writeto  <- lastest getArgs
    let folderl b = searchable <$> (getPermissions b)
    let filel   c = ((lastlookup mlookup c) &&) <$> ((not <$> folderl c))
    a <- listDirectory xs
    listdirs <- filterM (folderl) (map ((xs ++ "/") ++) a)
    filedirs <- filterM (filel)   (map ((xs ++ "/") ++) a)
    tagfiles <- tagsort <$> filedirs
--testprint to terminal
    putStrLn $ concat listdirs
    putStrLn $ concat tagfiles


tagsort :: Control.Monad.IO.Class.MonadIO m => FilePath -> m [Char]
tagsort xs = do
    nsartist <- getTags xs artistGetter
    nsalbum  <- getTags xs albumGetter
    let artist = init $ drop 8 $ show nsartist
    let album  = init $ drop 7 $ show nsalbum
    pure (artist ++ " - " ++ album)

我想使用此功能并将其映射到目录列表中。运行时,出现此错误。

• Couldn't match type ‘[]’ with ‘IO’
      Expected type: IO (t0 [Char])
        Actual type: [t0 [Char]]
    • In a stmt of a 'do' block: tagfiles <- tagsort <$> filedirs

我相信我了解这里发生的事情。为了以我希望的方式对标记文件进行绑定,我需要一个IO [String],但是将tagsort映射到列表filedirs会生成[IO String]。我不太确定如何规避它,甚至根本无法规避它。也许映射不是执行此操作的正确方法?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

这是因为函数tagsort的类型为String -> IO String
注意:为简单起见,我使用IO,而String[Char]都使用FilePath

但是,使用

将其映射到filedir :: [String]

(<$>) = fmap :: Functor f => (a -> b) -> f a -> f b

IO [String]与`[IO String]之间发生冲突-前者是编译器期望do块中的表达式是

乍一看,这不是很有用。但是,haskell具有一个名为sequence的函数来完成此确切任务。由于Foldable完全不同,因此它的约束现在不再重要。现在,知道它的类型可以为[IO a] -> IO [a]

再次幸运的是,有一个非常有用的预定义实用程序功能,mapM仅用于sequence . map f

最终代码为:

mapM tagSort fileDirs