0

I'm trying out Hakyll and having trouble fitting in IO type into Hakyll compilation process. Here's an example Hakyll code from tutorial.

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

I want to look at the list of localized files (en.md, fr.md, ...) in matched directories and produce a list of available languages, which I will use to generate urls for redirecting to translations. I think this logic will have to be placed around $1.

It's file operation so it produces IO [FilePath]. But $1 is inside Hakyll.Compiler monad, which is computed inside Hakyll.Rules and IO monads. Somehow I need to deal with IO type to work within the type signatures set by the library author. What is a good way to do this?

There are a few other implementations I can think of that avoid accessing file system and producing IO type, but I want to do it this way if possible. Plus, I want to get down to the bottom of this as it looks like a kind of issue that I may face commonly while writing Haskell.

luqui
  • 59,485
  • 12
  • 145
  • 204
Harfangk
  • 814
  • 9
  • 18

1 Answers1

2

It might not be necessary to use IO, and that should generally be avoided because it prevents Hakyll from tracking dependencies.

There is a loadAll function to get all items matching a pattern (in your case, possibly "posts/currentpost/*.md", that might need messing with getResourceFilePath to construct). Then given all those Item you can look at their itemIdentifier and extract the basenames/languages (fr, en...).

-- rough sketch

...
  compile $ do
    currentPath <- getResourceFilePath
    allItems <- loadAll ... :: Compiler [Item ()]  -- () ignores the contents
    let idens = map itemIdentifier allItems
        url = ... idens
    ...
Li-yao Xia
  • 31,896
  • 2
  • 33
  • 56
  • 1
    It almost worked... but Hakyll found circular dependency and refused to compile. When the initial matched item is `posts/quor/en.md`, `loadAll post/quor/*` ends up trying to load `posts/quor/en.md` again within the context of compiling the same file, causing circular dependency. This is a bit frustrating – Harfangk Jan 12 '19 at 11:54