0

我正在尝试 Hakyll,但无法将 IO 类型融入 Hakyll 编译过程。这是教程中的示例 Hakyll 代码。

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

我想查看匹配目录中的本地化文件列表(en.md、fr.md、...)并生成可用语言列表,我将使用它来生成用于重定向到翻译的 url。我认为这个逻辑必须放在$1.

它是文件操作,所以它产生IO [FilePath]. But $1is inside Hakyll.Compilermonad,它是在Hakyll.RulesIOmonads 内部计算的。不知何故,我需要处理IO类型以在库作者设置的类型签名中工作。有什么好方法可以做到这一点?

我能想到的其他一些实现可以避免访问文件系统和生成IO类型,但如果可能的话,我想这样做。另外,我想深入了解这一点,因为它看起来像是我在编写 Haskell 时可能经常遇到的一种问题。

4

1 回答 1

2

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

有一个loadAll函数可以获取与模式匹配的所有项目(在您的情况下,"posts/currentpost/*.md"可能需要弄乱getResourceFilePath构造)。然后给定所有这些Item,您可以查看它们itemIdentifier并提取基本名称/语言(fr... en)。

-- rough sketch

...
  compile $ do
    currentPath <- getResourceFilePath
    allItems <- loadAll ... :: Compiler [Item ()]  -- () ignores the contents
    let idens = map itemIdentifier allItems
        url = ... idens
    ...
于 2018-12-31T12:23:24.673 回答