@@ -1,4 +1,88 @@
1−-- | A Compiler manages targets and dependencies between targets.
1+-- | A Compiler manages targets and dependencies between targets
2+--
3+-- The most distinguishing property of a 'Compiler' is that it is an Arrow. A
4+-- compiler of the type @Compiler a b@ is simply a compilation phase which takes
5+-- an @a@ as input, and produces a @b@ as output.
6+--
7+-- Compilers are chained using the '>>>' arrow operation. If we have a compiler
8+--
9+-- > getResourceString :: Compiler Resource String
10+--
11+-- which reads the resource, and a compiler
12+--
13+-- > readPage :: Compiler String (Page String)
14+--
15+-- we can chain these two compilers to get a
16+--
17+-- > (getResourceString >>> readPage) :: Compiler Resource (Page String)
18+--
19+-- Most compilers can be created by combining smaller compilers using '>>>'.
20+--
21+-- More advanced constructions are also possible using arrow, and sometimes
22+-- these are needed. For a good introduction to arrow, you can refer to
23+--
24+-- <http://en.wikibooks.org/wiki/Haskell/Understanding_arrows>
25+--
26+-- A construction worth writing a few paragraphs about here are the 'require'
27+-- functions. Different variants of this function are exported here, but they
28+-- all serve more or less the same goal.
29+--
30+-- When you use only '>>>' to chain your compilers, you get a linear pipeline --
31+-- it is not possible to add extra items from other compilers along the way.
32+-- This is where the 'require' functions come in.
33+--
34+-- This function allows you to reference other items, which are then added to
35+-- the pipeline. Let's look at this crappy ASCII illustration which represents
36+-- a pretty common scenario:
37+--
38+-- > read resource >>> pandoc render >>> layout >>> relativize URL's
39+-- >
40+-- > @templates/fancy.html@
41+--
42+-- We want to construct a pipeline of compilers to go from our resource to a
43+-- proper webpage. However, the @layout@ compiler takes more than just the
44+-- rendered page as input: it needs the @templates/fancy.html@ template as well.
45+--
46+-- This is an example of where we need the @require@ function. We can solve
47+-- this using a construction that looks like:
48+--
49+-- > ... >>> pandoc render >>> require >>> layout >>> ...
50+-- > |
51+-- > @templates/fancy.html@ ------/
52+--
53+-- This illustration can help us understand the type signature of 'require'.
54+--
55+-- > require :: (Binary a, Typeable a, Writable a)
56+-- > => Identifier
57+-- > -> (b -> a -> c)
58+-- > -> Compiler b c
59+--
60+-- Let's look at it in detail:
61+--
62+-- > (Binary a, Typeable a, Writable a)
63+--
64+-- These are constraints for the @a@ type. @a@ (the template) needs to have
65+-- certain properties for it to be required.
66+--
67+-- > Identifier
68+--
69+-- This is simply @templates/fancy.html@: the 'Identifier' of the item we want
70+-- to 'require', in other words, the name of the item we want to add to the
71+-- pipeline somehow.
72+--
73+-- > (b -> a -> c)
74+--
75+-- This is a function given by the user, specifying /how/ the two items shall be
76+-- merged. @b@ is the output of the previous compiler, and @a@ is the item we
77+-- just required -- the template. This means @c@ will be the final output of the
78+-- 'require' combinator.
79+--
80+-- > Compiler b c
81+--
82+-- Indeed, we have now constructed a compiler which takes a @b@ and produces a
83+-- @c@. This means that we have a linear pipeline again, thanks to the 'require'
84+-- function. So, the 'require' function actually helps to reduce to complexity
85+-- of Hakyll applications!
286--
387{-# LANGUAGE GeneralizedNewtypeDeriving #-}
488module Hakyll.Core.Compiler