2

Earlier I asked a question about having two independent lists render on a given page, which was kindly answered. Now, I wish to alphabetise that list - and to show all items in the list (which I believe I can see how to do, but I have been focusing on the first issue.)

In trying to do this, I came up with something like this after a few failed attempts (which is actually the same as here, because it was more elegant than my code by miles):

alphaOrder :: MonadMetadata m => [Item a] -> m [Item a]
alphaOrder =
    sortByM $ getItemPath . itemIdentifier
  where
    sortByM :: (Monad m, Ord k) => (a -> m k) -> [a] -> m [a]
    sortByM f xs = liftM (map fst . sortBy (comparing snd)) $
                   mapM (\x -> liftM (x,) (f x)) xs

getItemPath :: MonadMetadata m
           => Identifier        -- ^ Input page
           -> m FilePath        -- ^ Parsed UTCTime
getItemPath id' = return $ toFilePath id'
-- |                                             page-id order
data ItemTree a = ItemTree (Item a) [ItemTree a] String  String
type ItemPath a = ( Item a, [FilePath])

itemPath :: [ Item a] -> [ ItemPath a]
itemPath =
  map (\i -> ( i, splitDirectories
               . dropExtensions . toFilePath . itemIdentifier $ i) )

which I tried to apply like so:

create ["bibs.html"] $ do
    route idRoute
    compile $ do
        list <- bibList tags "bibs/*" alphaOrder
        makeItem list
            >>= loadAndApplyTemplate "templates/posts.html" allBibsCtx
            >>= loadAndApplyTemplate "templates/default.html" allBibsCtx
            >>= relativizeUrls

-- Index
create ["index.html"] $ do
    route idRoute
    compile $ do
        let mkposts = postList tags "posts/*" (fmap (Prelude.take 10) . recentFirst)
            mkbibs = bibList tags "bibs/*" (fmap (Prelude.take 10) . alphaOrder)
            homeCtx' = field "posts" (const mkposts)
                    <> field "bibs" (const mkbibs)
                    <> homeCtx
        makeItem ""
            >>= loadAndApplyTemplate "templates/index.html"   homeCtx'
            >>= loadAndApplyTemplate "templates/default.html" homeCtx'
            >>= relativizeUrls

however, on trying to build, I got an error:

error: Illegal tuple section: use TupleSections
   |
55 |                    mapM (\x -> liftM (x,) (f x)) xs
   |                                      ^^^^

so now I have enabled TupleSections and it builds - but the list still isn't rendered in alphabetical order.

What am I doing wrong?

Thank you in advance and let me know if I can clarify anything.

Edit:

The implementation of bibList:

bibList :: Tags -> Pattern -> ([Item String] -> Compiler [Item String]) -> Compiler String
bibList tags pattern preprocess' = do
    postItemTpl <- loadBody "templates/postitem.html"
    posts <- preprocess' =<< loadAll pattern
    applyTemplateList postItemTpl (tagsCtx tags) posts
  • Why this complicated monadic sorting? You can strip the `return` from `getItemPath`, returning a plain `FilePath`, which should make everything easier. – Bergi Aug 13 '20 at 22:00
  • Can you post the implementation of `bibList`, please? – Bergi Aug 13 '20 at 22:05
  • @Bergi I've added `bibList`. As for the sorting, I do not really have a reason - I am quite new to Haskell and Hakyll and was mostly blindly trying things. I will be studying more to try to make maintaining this site easier, it seems clear I am trying to run before walking. – Kartöfluvofan Aug 13 '20 at 22:13

1 Answers1

0

All that was needed was

alphaOrder :: [Item a] -> Compiler [Item a]
alphaOrder items = return $
              sortBy (comparing (takeBaseName . toFilePath . itemIdentifier)) items