@@ -0,0 +1,87 @@
1+---
2+title: Tutorial (Part VI)
3+what: explains how to use categories instead of tags
4+---
5+
6+## Categories
7+
8+Most people familiar with "tags" will also know the concept "categories".
9+
10+
11+
12+In fact, tags are harder to implement because they have to be represented as a
13+many-to-many relation, and categories are a simple 1-to-many relation.
14+
15+
16+
17+This is also the reason you can "simulate" categories using tags. In this
18+tutorial we will adapt the blog to use categories instead of tags. Here is
19+[a zip file](examples/categoryblog.zip) containing the files used in this
20+tutorial.
21+
22+## Reading Categories
23+
24+Tags are located in the `tags` metadata field. Since one post can only belong
25+in one category, a different approach was chosen here. The category of a post
26+is determined by the subfolder it is in. Here you see the directory layout for
27+our posts using categories:
28+
29+ posts
30+ |-- coding
31+ | |-- 2009-11-05-a-first-post.markdown
32+ | |-- 2009-11-28-a-third-post.markdown
33+ | `-- 2009-12-04-this-blog-aint-dead.markdown
34+ `-- random
35+ |-- 2009-11-10-another-post.markdown
36+ `-- 2009-12-23-almost-christmas.markdown
37+
38+Because we find all our posts in different subdirectories, sorting them is a
39+little harder: we still want them sorted by date, so it boils down to sorting
40+them by "base name". I hope it does not surprise you Hakyll provides a function
41+for that:
42+
43+~~~~~{.haskell}
44+postPaths <- liftM (reverse . sortByBaseName)
45+ (getRecursiveContents "posts")
46+~~~~~
47+
48+Now, we can use the `readCategoryMap` function instead of `readTagMap`, which
49+has the same signature, but assigns categories based on the folders the posts
50+are in.
51+
52+~~~~~{.haskell}
53+categoryMap <- readCategoryMap "categoryMap" renderablePosts
54+~~~~~
55+
56+The rest of the `hakyll.hs` is very similar to the one in the previous
57+tutorial, except we want to render a category list instead of a tag cloud.
58+
59+## Rendering a category list
60+
61+Because rendering a category list is quite easy, and it would be hard to
62+write a "general" function for this, hakyll does not provide such a function -
63+but it is not hard to write. First, we write an auxiliary function that produces
64+a list item for one category:
65+
66+~~~~~{.haskell}
67+categoryListItem category posts =
68+ "<li>" ++ link category (categoryToURL category)
69+ ++ " - " ++ show (length posts) ++ " items.</li>"
70+~~~~~
71+
72+This is nothing more that some string concatenation. The function that applies
73+this on every element in the `TagMap` is more interesting:
74+
75+~~~~~{.haskell}
76+categoryList :: TagMap -> String
77+categoryList = uncurry categoryListItem <=< toList
78+~~~~~
79+
80+This function might seem a little harder to understand, and figuring out how it
81+works is left as an exercise for the reader[^1].
82+
83+[^1]: Hint: `>>=` is `concatMap` in the list monad.
84+
85+We then add this to our index page, and we are done. Feel free to hack around
86+with the source code. If you still have questions, feel free to ask them at the
87+[google discussion group](http://groups.google.com/group/hakyll).