Как вписаться в тип ввода-вывода при использовании внешних библиотек - PullRequest
0 голосов
/ 31 декабря 2018

Я пробую 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].Но $1 находится внутри Hakyll.Compiler монады, которая вычисляется внутри Hakyll.Rules и IO монад.Каким-то образом мне нужно работать с типом IO, чтобы работать в сигнатурах типов, установленных автором библиотеки.Каков хороший способ сделать это?

Есть несколько других реализаций, о которых я могу подумать, чтобы избежать доступа к файловой системе и создания типа IO, но я хочу сделать это таким образом, если это возможно.Кроме того, я хочу перейти к сути, так как это похоже на проблему, с которой я часто сталкиваюсь при написании Haskell.

1 Ответ

0 голосов
/ 31 декабря 2018

Возможно, нет необходимости использовать 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
    ...
...