使用外部库时如何适应 IO 类型

How to fit in IO type when using external libraries

我正在试用 Hakyll,但在将 IO 类型装入 Hakyll 编译过程时遇到了问题。这是教程中的示例 Hakyll 代码。

main :: IO ()
main = hakyll $ do
    match "posts/*" $ do
        route $ setExtension "html"
        compile $ do
            let url = -- 
                ctx = stringField "title" url `mappend` defaultCtx
                in
                pandocCompiler
                >>= loadAndApplyTemplate "templates/default.html" ctx
                >>= relativizeUrls

我想查看匹配目录中的本地化文件列表(en.md、fr.md、...)并生成可用语言列表,我将使用它来生成 url用于重定向到翻译。我认为这个逻辑必须放在 </code>.</p> 周围 <p>它是文件操作所以它产生 <code>IO [FilePath]。但是 </code> 在 <code>Hakyll.Compiler monad 内部,它是在 Hakyll.RulesIO monad 内部计算的。我需要以某种方式处理 IO 类型以在库作者设置的类型签名内工作。这样做的好方法是什么?

还有一些我能想到的避免访问文件系统和生成 IO 类型的实现,但如果可能的话我想这样做。另外,我想追根究底,因为它看起来像是我在写作 Haskell 时可能经常遇到的一种问题。

可能没有必要使用 IO,通常应避免使用,因为它会阻止 Hakyll 跟踪依赖项。

有一个 loadAll 函数可以让所有项目匹配一个模式(在你的情况下,可能 "posts/currentpost/*.md",这可能需要弄乱 getResourceFilePath 来构建)。然后给出所有这些 Item 你可以看看他们的 itemIdentifier 并提取 basenames/languages (fr, en...).

-- rough sketch

...
  compile $ do
    currentPath <- getResourceFilePath
    allItems <- loadAll ... :: Compiler [Item ()]  -- () ignores the contents
    let idens = map itemIdentifier allItems
        url = ... idens
    ...