在这里的这段代码中,我有一个函数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]
。我不太确定如何规避它,甚至根本无法规避它。也许映射不是执行此操作的正确方法?任何帮助将不胜感激。
答案 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