on master help sign in
Type-safe identifiers
758e0beJasper Van der Jeugt
src/Hakyll/Core/Compiler.hs+14−12
@@ -142,9 +142,9 @@ import Hakyll.Core.Logger
142-- version of 'runCompilerJob' also stores the result
142-- version of 'runCompilerJob' also stores the result
143--
143--
144runCompiler :: Compiler () CompileRule -- ^ Compiler to run
144runCompiler :: Compiler () CompileRule -- ^ Compiler to run
145− -> Identifier -- ^ Target identifier
145+ -> Identifier () -- ^ Target identifier
146 -> ResourceProvider -- ^ Resource provider
146 -> ResourceProvider -- ^ Resource provider
147− -> [Identifier] -- ^ Universe
147+ -> [Identifier ()] -- ^ Universe
148 -> Routes -- ^ Route
148 -> Routes -- ^ Route
149 -> Store -- ^ Store
149 -> Store -- ^ Store
150 -> Bool -- ^ Was the resource modified?
150 -> Bool -- ^ Was the resource modified?
@@ -161,7 +161,8 @@ runCompiler compiler id' provider universe routes store modified logger = do
161 -- before we return control. This makes sure the compiled item can later
161 -- before we return control. This makes sure the compiled item can later
162 -- be accessed by e.g. require.
162 -- be accessed by e.g. require.
163 Right (CompileRule (CompiledItem x)) ->
163 Right (CompileRule (CompiledItem x)) ->
164− storeSet store "Hakyll.Core.Compiler.runCompiler" id' x
164+ storeSet store "Hakyll.Core.Compiler.runCompiler"
165+ (castIdentifier id') x
165
166
166 -- Otherwise, we do nothing here
167 -- Otherwise, we do nothing here
167 _ -> return ()
168 _ -> return ()
@@ -170,8 +171,9 @@ runCompiler compiler id' provider universe routes store modified logger = do
170
171
171-- | Get the identifier of the item that is currently being compiled
172-- | Get the identifier of the item that is currently being compiled
172--
173--
173−getIdentifier :: Compiler a Identifier
174+getIdentifier :: Compiler a (Identifier b)
174−getIdentifier = fromJob $ const $ CompilerM $ compilerIdentifier <$> ask
175+getIdentifier = fromJob $ const $ CompilerM $
176+ castIdentifier . compilerIdentifier <$> ask
175
177
176-- | Get the route we are using for this item
178-- | Get the route we are using for this item
177--
179--
@@ -180,7 +182,7 @@ getRoute = getIdentifier >>> getRouteFor
180
182
181-- | Get the route for a specified item
183-- | Get the route for a specified item
182--
184--
183−getRouteFor :: Compiler Identifier (Maybe FilePath)
185+getRouteFor :: Compiler (Identifier a) (Maybe FilePath)
184getRouteFor = fromJob $ \identifier -> CompilerM $ do
186getRouteFor = fromJob $ \identifier -> CompilerM $ do
185 routes <- compilerRoutes <$> ask
187 routes <- compilerRoutes <$> ask
186 return $ runRoutes routes identifier
188 return $ runRoutes routes identifier
@@ -212,7 +214,7 @@ getResourceWith reader = fromJob $ \resource -> CompilerM $ do
212-- | Auxiliary: get a dependency
214-- | Auxiliary: get a dependency
213--
215--
214getDependency :: (Binary a, Writable a, Typeable a)
216getDependency :: (Binary a, Writable a, Typeable a)
215− => Identifier -> CompilerM a
217+ => Identifier a -> CompilerM a
216getDependency id' = CompilerM $ do
218getDependency id' = CompilerM $ do
217 store <- compilerStore <$> ask
219 store <- compilerStore <$> ask
218 result <- liftIO $ storeGet store "Hakyll.Core.Compiler.runCompiler" id'
220 result <- liftIO $ storeGet store "Hakyll.Core.Compiler.runCompiler" id'
@@ -233,7 +235,7 @@ getDependency id' = CompilerM $ do
233-- | Variant of 'require' which drops the current value
235-- | Variant of 'require' which drops the current value
234--
236--
235require_ :: (Binary a, Typeable a, Writable a)
237require_ :: (Binary a, Typeable a, Writable a)
236− => Identifier
238+ => Identifier a
237 -> Compiler b a
239 -> Compiler b a
238require_ identifier =
240require_ identifier =
239 fromDependency identifier >>> fromJob (const $ getDependency identifier)
241 fromDependency identifier >>> fromJob (const $ getDependency identifier)
@@ -242,7 +244,7 @@ require_ identifier =
242-- dependencies
244-- dependencies
243--
245--
244require :: (Binary a, Typeable a, Writable a)
246require :: (Binary a, Typeable a, Writable a)
245− => Identifier
247+ => Identifier a
246 -> (b -> a -> c)
248 -> (b -> a -> c)
247 -> Compiler b c
249 -> Compiler b c
248require identifier = requireA identifier . arr . uncurry
250require identifier = requireA identifier . arr . uncurry
@@ -250,7 +252,7 @@ require identifier = requireA identifier . arr . uncurry
250-- | Arrow-based variant of 'require'
252-- | Arrow-based variant of 'require'
251--
253--
252requireA :: (Binary a, Typeable a, Writable a)
254requireA :: (Binary a, Typeable a, Writable a)
253− => Identifier
255+ => Identifier a
254 -> Compiler (b, a) c
256 -> Compiler (b, a) c
255 -> Compiler b c
257 -> Compiler b c
256requireA identifier = (id &&& require_ identifier >>>)
258requireA identifier = (id &&& require_ identifier >>>)
@@ -262,7 +264,7 @@ requireAll_ :: (Binary a, Typeable a, Writable a)
262 -> Compiler b [a]
264 -> Compiler b [a]
263requireAll_ pattern = fromDependencies (const getDeps) >>> fromJob requireAll_'
265requireAll_ pattern = fromDependencies (const getDeps) >>> fromJob requireAll_'
264 where
266 where
265− getDeps = filterMatches pattern
267+ getDeps = map castIdentifier . filterMatches pattern . map castIdentifier
266 requireAll_' = const $ CompilerM $ do
268 requireAll_' = const $ CompilerM $ do
267 deps <- getDeps . compilerUniverse <$> ask
269 deps <- getDeps . compilerUniverse <$> ask
268 mapM (unCompilerM . getDependency) deps
270 mapM (unCompilerM . getDependency) deps
@@ -290,7 +292,7 @@ cached :: (Binary a, Typeable a, Writable a)
290 -> Compiler Resource a
292 -> Compiler Resource a
291cached name (Compiler d j) = Compiler d $ const $ CompilerM $ do
293cached name (Compiler d j) = Compiler d $ const $ CompilerM $ do
292 logger <- compilerLogger <$> ask
294 logger <- compilerLogger <$> ask
293− identifier <- compilerIdentifier <$> ask
295+ identifier <- castIdentifier . compilerIdentifier <$> ask
294 store <- compilerStore <$> ask
296 store <- compilerStore <$> ask
295 modified <- compilerResourceModified <$> ask
297 modified <- compilerResourceModified <$> ask
296 report logger $ "Checking cache: " ++ if modified then "modified" else "OK"
298 report logger $ "Checking cache: " ++ if modified then "modified" else "OK"
src/Hakyll/Core/Compiler/Internal.hs+12−12
@@ -33,26 +33,26 @@ import Hakyll.Core.Logger
33
33
34-- | A set of dependencies
34-- | A set of dependencies
35--
35--
36−type Dependencies = Set Identifier
36+type Dependencies = Set (Identifier ())
37
37
38-- | Environment in which the dependency analyzer runs
38-- | Environment in which the dependency analyzer runs
39--
39--
40data DependencyEnvironment = DependencyEnvironment
40data DependencyEnvironment = DependencyEnvironment
41 { -- | Target identifier
41 { -- | Target identifier
42− dependencyIdentifier :: Identifier
42+ dependencyIdentifier :: Identifier ()
43 , -- | List of available identifiers we can depend upon
43 , -- | List of available identifiers we can depend upon
44− dependencyUniverse :: [Identifier]
44+ dependencyUniverse :: [Identifier ()]
45 }
45 }
46
46
47-- | Environment in which a compiler runs
47-- | Environment in which a compiler runs
48--
48--
49data CompilerEnvironment = CompilerEnvironment
49data CompilerEnvironment = CompilerEnvironment
50 { -- | Target identifier
50 { -- | Target identifier
51− compilerIdentifier :: Identifier
51+ compilerIdentifier :: Identifier ()
52 , -- | Resource provider
52 , -- | Resource provider
53 compilerResourceProvider :: ResourceProvider
53 compilerResourceProvider :: ResourceProvider
54 , -- | List of all known identifiers
54 , -- | List of all known identifiers
55− compilerUniverse :: [Identifier]
55+ compilerUniverse :: [Identifier ()]
56 , -- | Site routes
56 , -- | Site routes
57 compilerRoutes :: Routes
57 compilerRoutes :: Routes
58 , -- | Compiler store
58 , -- | Compiler store
@@ -107,9 +107,9 @@ instance ArrowChoice Compiler where
107-- | Run a compiler, yielding the resulting target
107-- | Run a compiler, yielding the resulting target
108--
108--
109runCompilerJob :: Compiler () a -- ^ Compiler to run
109runCompilerJob :: Compiler () a -- ^ Compiler to run
110− -> Identifier -- ^ Target identifier
110+ -> Identifier () -- ^ Target identifier
111 -> ResourceProvider -- ^ Resource provider
111 -> ResourceProvider -- ^ Resource provider
112− -> [Identifier] -- ^ Universe
112+ -> [Identifier ()] -- ^ Universe
113 -> Routes -- ^ Route
113 -> Routes -- ^ Route
114 -> Store -- ^ Store
114 -> Store -- ^ Store
115 -> Bool -- ^ Was the resource modified?
115 -> Bool -- ^ Was the resource modified?
@@ -129,8 +129,8 @@ runCompilerJob compiler id' provider universe route store modified logger =
129 }
129 }
130
130
131runCompilerDependencies :: Compiler () a
131runCompilerDependencies :: Compiler () a
132− -> Identifier
132+ -> Identifier ()
133− -> [Identifier]
133+ -> [Identifier ()]
134 -> Dependencies
134 -> Dependencies
135runCompilerDependencies compiler identifier universe =
135runCompilerDependencies compiler identifier universe =
136 runReader (compilerDependencies compiler) env
136 runReader (compilerDependencies compiler) env
@@ -144,7 +144,7 @@ fromJob :: (a -> CompilerM b)
144 -> Compiler a b
144 -> Compiler a b
145fromJob = Compiler (return S.empty)
145fromJob = Compiler (return S.empty)
146
146
147−fromDependencies :: (Identifier -> [Identifier] -> [Identifier])
147+fromDependencies :: (Identifier () -> [Identifier ()] -> [Identifier ()])
148 -> Compiler b b
148 -> Compiler b b
149fromDependencies collectDeps = flip Compiler return $ do
149fromDependencies collectDeps = flip Compiler return $ do
150 DependencyEnvironment identifier universe <- ask
150 DependencyEnvironment identifier universe <- ask
@@ -152,5 +152,5 @@ fromDependencies collectDeps = flip Compiler return $ do
152
152
153-- | Wait until another compiler has finished before running this compiler
153-- | Wait until another compiler has finished before running this compiler
154--
154--
155−fromDependency :: Identifier -> Compiler a a
155+fromDependency :: Identifier a -> Compiler b b
156−fromDependency = fromDependencies . const . const . return
156+fromDependency = fromDependencies . const . const . return . castIdentifier
src/Hakyll/Core/Identifier.hs+21−8
@@ -23,6 +23,7 @@
23{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveDataTypeable #-}
23{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveDataTypeable #-}
24module Hakyll.Core.Identifier
24module Hakyll.Core.Identifier
25 ( Identifier (..)
25 ( Identifier (..)
26+ , castIdentifier
26 , parseIdentifier
27 , parseIdentifier
27 , toFilePath
28 , toFilePath
28 , setGroup
29 , setGroup
@@ -40,30 +41,42 @@ import Data.Typeable (Typeable)
40
41
41-- | An identifier used to uniquely identify a value
42-- | An identifier used to uniquely identify a value
42--
43--
44+-- The @a@ is used to denote the type that the identifier points to. It is a
45+-- phantom type parameter, meaning you can safely change this if you know what
46+-- you are doing.
47+--
48+-- If the @a@ type is not known, Hakyll traditionally uses @Identifier ()@.
49+--
43−data Identifier = Identifier
50+data Identifier a = Identifier
44 { identifierGroup :: Maybe String
51 { identifierGroup :: Maybe String
45 , identifierPath :: String
52 , identifierPath :: String
46 } deriving (Eq, Ord, Typeable)
53 } deriving (Eq, Ord, Typeable)
47
54
48−instance Monoid Identifier where
55+instance Monoid (Identifier a) where
49 mempty = Identifier Nothing ""
56 mempty = Identifier Nothing ""
50 Identifier g1 p1 `mappend` Identifier g2 p2 =
57 Identifier g1 p1 `mappend` Identifier g2 p2 =
51 Identifier (g1 `mplus` g2) (p1 `mappend` p2)
58 Identifier (g1 `mplus` g2) (p1 `mappend` p2)
52
59
53−instance Binary Identifier where
60+instance Binary (Identifier a) where
54 put (Identifier g p) = put g >> put p
61 put (Identifier g p) = put g >> put p
55 get = Identifier <$> get <*> get
62 get = Identifier <$> get <*> get
56
63
57−instance Show Identifier where
64+instance Show (Identifier a) where
58 show i@(Identifier Nothing _) = toFilePath i
65 show i@(Identifier Nothing _) = toFilePath i
59 show i@(Identifier (Just g) _) = toFilePath i ++ " (" ++ g ++ ")"
66 show i@(Identifier (Just g) _) = toFilePath i ++ " (" ++ g ++ ")"
60
67
61−instance IsString Identifier where
68+instance IsString (Identifier a) where
62 fromString = parseIdentifier
69 fromString = parseIdentifier
63
70
71+-- | Discard the phantom type parameter of an identifier
72+--
73+castIdentifier :: Identifier a -> Identifier b
74+castIdentifier (Identifier g p) = Identifier g p
75+{-# INLINE castIdentifier #-}
76+
64-- | Parse an identifier from a string
77-- | Parse an identifier from a string
65--
78--
66−parseIdentifier :: String -> Identifier
79+parseIdentifier :: String -> Identifier a
67parseIdentifier = Identifier Nothing
80parseIdentifier = Identifier Nothing
68 . intercalate "/" . filter (not . null) . split'
81 . intercalate "/" . filter (not . null) . split'
69 where
82 where
@@ -73,10 +86,10 @@ parseIdentifier = Identifier Nothing
73
86
74-- | Convert an identifier to a relative 'FilePath'
87-- | Convert an identifier to a relative 'FilePath'
75--
88--
76−toFilePath :: Identifier -> FilePath
89+toFilePath :: Identifier a -> FilePath
77toFilePath = identifierPath
90toFilePath = identifierPath
78
91
79-- | Set the identifier group for some identifier
92-- | Set the identifier group for some identifier
80--
93--
81−setGroup :: Maybe String -> Identifier -> Identifier
94+setGroup :: Maybe String -> Identifier a -> Identifier a
82setGroup g (Identifier _ p) = Identifier g p
95setGroup g (Identifier _ p) = Identifier g p
src/Hakyll/Core/Identifier/Pattern.hs+11−10
@@ -66,8 +66,8 @@ data GlobComponent = Capture
66-- | Type that allows matching on identifiers
66-- | Type that allows matching on identifiers
67--
67--
68data Pattern a = Glob [GlobComponent]
68data Pattern a = Glob [GlobComponent]
69− | Predicate (Identifier -> Bool)
69+ | Predicate (Identifier a -> Bool)
70− | List [Identifier]
70+ | List [Identifier a]
71
71
72instance IsString (Pattern a) where
72instance IsString (Pattern a) where
73 fromString = parseGlob
73 fromString = parseGlob
@@ -80,8 +80,9 @@ instance Monoid (Pattern a) where
80--
80--
81castPattern :: Pattern a -> Pattern b
81castPattern :: Pattern a -> Pattern b
82castPattern (Glob g) = Glob g
82castPattern (Glob g) = Glob g
83−castPattern (Predicate p) = Predicate p
83+castPattern (Predicate p) = Predicate $ p . castIdentifier
84−castPattern (List l) = List l
84+castPattern (List l) = List $ map castIdentifier l
85+{-# INLINE castPattern #-}
85
86
86-- | Parse a pattern from a string
87-- | Parse a pattern from a string
87--
88--
@@ -102,7 +103,7 @@ parseGlob = Glob . parse'
102--
103--
103-- > predicate (\i -> matches "foo/*" i && not (matches "foo/bar" i))
104-- > predicate (\i -> matches "foo/*" i && not (matches "foo/bar" i))
104--
105--
105−predicate :: (Identifier -> Bool) -> Pattern a
106+predicate :: (Identifier a -> Bool) -> Pattern a
106predicate = Predicate
107predicate = Predicate
107
108
108-- | Create a 'Pattern' from a regex
109-- | Create a 'Pattern' from a regex
@@ -122,14 +123,14 @@ inGroup group = predicate $ (== group) . identifierGroup
122
123
123-- | Check if an identifier matches a pattern
124-- | Check if an identifier matches a pattern
124--
125--
125−matches :: Pattern a -> Identifier -> Bool
126+matches :: Pattern a -> Identifier a -> Bool
126matches (Glob p) = isJust . capture (Glob p)
127matches (Glob p) = isJust . capture (Glob p)
127matches (Predicate p) = (p $)
128matches (Predicate p) = (p $)
128matches (List l) = (`elem` l)
129matches (List l) = (`elem` l)
129
130
130-- | Given a list of identifiers, retain only those who match the given pattern
131-- | Given a list of identifiers, retain only those who match the given pattern
131--
132--
132−filterMatches :: Pattern a -> [Identifier] -> [Identifier]
133+filterMatches :: Pattern a -> [Identifier a] -> [Identifier a]
133filterMatches = filter . matches
134filterMatches = filter . matches
134
135
135-- | Split a list at every possible point, generate a list of (init, tail)
136-- | Split a list at every possible point, generate a list of (init, tail)
@@ -140,7 +141,7 @@ splits = inits &&& tails >>> uncurry zip >>> reverse
140
141
141-- | Match a glob against a pattern, generating a list of captures
142-- | Match a glob against a pattern, generating a list of captures
142--
143--
143−capture :: Pattern a -> Identifier -> Maybe [String]
144+capture :: Pattern a -> Identifier a -> Maybe [String]
144capture (Glob p) (Identifier _ i) = capture' p i
145capture (Glob p) (Identifier _ i) = capture' p i
145capture _ _ = Nothing
146capture _ _ = Nothing
146
147
@@ -172,13 +173,13 @@ capture' (CaptureMany : ms) str =
172--
173--
173-- > "tags/foo"
174-- > "tags/foo"
174--
175--
175−fromCapture :: Pattern a -> String -> Identifier
176+fromCapture :: Pattern a -> String -> Identifier a
176fromCapture pattern = fromCaptures pattern . repeat
177fromCapture pattern = fromCaptures pattern . repeat
177
178
178-- | Create an identifier from a pattern by filling in the captures with the
179-- | Create an identifier from a pattern by filling in the captures with the
179-- given list of strings
180-- given list of strings
180--
181--
181−fromCaptures :: Pattern a -> [String] -> Identifier
182+fromCaptures :: Pattern a -> [String] -> Identifier a
182fromCaptures (Glob p) = Identifier Nothing . fromCaptures' p
183fromCaptures (Glob p) = Identifier Nothing . fromCaptures' p
183fromCaptures _ = error $
184fromCaptures _ = error $
184 "Hakyll.Core.Identifier.Pattern.fromCaptures: fromCaptures only works " ++
185 "Hakyll.Core.Identifier.Pattern.fromCaptures: fromCaptures only works " ++
src/Hakyll/Core/Resource.hs+2−2
@@ -15,10 +15,10 @@ newtype Resource = Resource {unResource :: String}
15
15
16-- | Create a resource from an identifier
16-- | Create a resource from an identifier
17--
17--
18−fromIdentifier :: Identifier -> Resource
18+fromIdentifier :: Identifier a -> Resource
19fromIdentifier = Resource . toFilePath
19fromIdentifier = Resource . toFilePath
20
20
21-- | Map the resource to an identifier. Note that the group will not be set!
21-- | Map the resource to an identifier. Note that the group will not be set!
22--
22--
23−toIdentifier :: Resource -> Identifier
23+toIdentifier :: Resource -> Identifier a
24toIdentifier = parseIdentifier . unResource
24toIdentifier = parseIdentifier . unResource
src/Hakyll/Core/Routes.hs+6−5
@@ -25,6 +25,7 @@
25--
25--
26-- * If an item matches multiple routes, the first rule will be chosen.
26-- * If an item matches multiple routes, the first rule will be chosen.
27--
27--
28+{-# LANGUAGE Rank2Types #-}
28module Hakyll.Core.Routes
29module Hakyll.Core.Routes
29 ( Routes
30 ( Routes
30 , runRoutes
31 , runRoutes
@@ -46,7 +47,7 @@ import Hakyll.Core.Util.String
46
47
47-- | Type used for a route
48-- | Type used for a route
48--
49--
49−newtype Routes = Routes {unRoutes :: Identifier -> Maybe FilePath}
50+newtype Routes = Routes {unRoutes :: forall a. Identifier a -> Maybe FilePath}
50
51
51instance Monoid Routes where
52instance Monoid Routes where
52 mempty = Routes $ const Nothing
53 mempty = Routes $ const Nothing
@@ -54,7 +55,7 @@ instance Monoid Routes where
54
55
55-- | Apply a route to an identifier
56-- | Apply a route to an identifier
56--
57--
57−runRoutes :: Routes -> Identifier -> Maybe FilePath
58+runRoutes :: Routes -> Identifier a -> Maybe FilePath
58runRoutes = unRoutes
59runRoutes = unRoutes
59
60
60-- | A route that uses the identifier as filepath. For example, the target with
61-- | A route that uses the identifier as filepath. For example, the target with
@@ -90,13 +91,13 @@ setExtension extension = Routes $ fmap (`replaceExtension` extension)
90--
91--
91matchRoute :: Pattern a -> Routes -> Routes
92matchRoute :: Pattern a -> Routes -> Routes
92matchRoute pattern (Routes route) = Routes $ \id' ->
93matchRoute pattern (Routes route) = Routes $ \id' ->
93− if matches pattern id' then route id' else Nothing
94+ if matches pattern (castIdentifier id') then route id' else Nothing
94
95
95-- | Create a custom route. This should almost always be used with
96-- | Create a custom route. This should almost always be used with
96-- 'matchRoute'
97-- 'matchRoute'
97--
98--
98−customRoute :: (Identifier -> FilePath) -> Routes
99+customRoute :: (Identifier a -> FilePath) -> Routes
99−customRoute f = Routes $ Just . f
100+customRoute f = Routes $ Just . f . castIdentifier
100
101
101-- | Create a gsub route
102-- | Create a gsub route
102--
103--
src/Hakyll/Core/Rules.hs+10−10
@@ -31,7 +31,7 @@ module Hakyll.Core.Rules
31import Control.Applicative ((<$>))
31import Control.Applicative ((<$>))
32import Control.Monad.Writer (tell)
32import Control.Monad.Writer (tell)
33import Control.Monad.Reader (ask, local)
33import Control.Monad.Reader (ask, local)
34−import Control.Arrow (second, (>>>), arr, (>>^), (***))
34+import Control.Arrow ((>>>), arr, (>>^), (***))
35import Control.Monad.State (get, put)
35import Control.Monad.State (get, put)
36import Data.Monoid (mempty, mappend)
36import Data.Monoid (mempty, mappend)
37import qualified Data.Set as S
37import qualified Data.Set as S
@@ -58,13 +58,13 @@ tellRoute route' = RulesM $ tell $ RuleSet route' mempty mempty
58-- | Add a number of compilers
58-- | Add a number of compilers
59--
59--
60tellCompilers :: (Binary a, Typeable a, Writable a)
60tellCompilers :: (Binary a, Typeable a, Writable a)
61− => [(Identifier, Compiler () a)]
61+ => [(Identifier a, Compiler () a)]
62 -> Rules
62 -> Rules
63tellCompilers compilers = RulesM $ do
63tellCompilers compilers = RulesM $ do
64 -- We box the compilers so they have a more simple type, and we apply the
64 -- We box the compilers so they have a more simple type, and we apply the
65 -- current group to the corresponding identifiers
65 -- current group to the corresponding identifiers
66− group' <- rulesGroup <$> ask
66+ g <- rulesGroup <$> ask
67− let compilers' = map (setGroup group' *** boxCompiler) compilers
67+ let compilers' = map (setGroup g . castIdentifier *** boxCompiler) compilers
68 tell $ RuleSet mempty compilers' mempty
68 tell $ RuleSet mempty compilers' mempty
69 where
69 where
70 boxCompiler = (>>> arr compiledItem >>> arr CompileRule)
70 boxCompiler = (>>> arr compiledItem >>> arr CompileRule)
@@ -143,7 +143,7 @@ compile compiler = do
143-- actual content itself.
143-- actual content itself.
144--
144--
145create :: (Binary a, Typeable a, Writable a)
145create :: (Binary a, Typeable a, Writable a)
146− => Identifier -> Compiler () a -> Rules
146+ => Identifier a -> Compiler () a -> Rules
147create identifier compiler = tellCompilers [(identifier, compiler)]
147create identifier compiler = tellCompilers [(identifier, compiler)]
148
148
149-- | Add a route.
149-- | Add a route.
@@ -160,7 +160,7 @@ route route' = RulesM $ do
160
160
161-- | Get a list of resources matching the current pattern
161-- | Get a list of resources matching the current pattern
162--
162--
163−resources :: RulesM [Identifier]
163+resources :: RulesM [Identifier a]
164resources = RulesM $ do
164resources = RulesM $ do
165 pattern <- rulesPattern <$> ask
165 pattern <- rulesPattern <$> ask
166 provider <- rulesResourceProvider <$> ask
166 provider <- rulesResourceProvider <$> ask
@@ -197,7 +197,7 @@ resources = RulesM $ do
197-- which items must be rendered.
197-- which items must be rendered.
198--
198--
199metaCompile :: (Binary a, Typeable a, Writable a)
199metaCompile :: (Binary a, Typeable a, Writable a)
200− => Compiler () [(Identifier, Compiler () a)]
200+ => Compiler () [(Identifier a, Compiler () a)]
201 -- ^ Compiler generating the other compilers
201 -- ^ Compiler generating the other compilers
202 -> Rules
202 -> Rules
203 -- ^ Resulting rules
203 -- ^ Resulting rules
@@ -217,9 +217,9 @@ metaCompile compiler = RulesM $ do
217-- the metacompiler.
217-- the metacompiler.
218--
218--
219metaCompileWith :: (Binary a, Typeable a, Writable a)
219metaCompileWith :: (Binary a, Typeable a, Writable a)
220− => Identifier
220+ => Identifier ()
221 -- ^ Identifier for this compiler
221 -- ^ Identifier for this compiler
222− -> Compiler () [(Identifier, Compiler () a)]
222+ -> Compiler () [(Identifier a, Compiler () a)]
223 -- ^ Compiler generating the other compilers
223 -- ^ Compiler generating the other compilers
224 -> Rules
224 -> Rules
225 -- ^ Resulting rules
225 -- ^ Resulting rules
@@ -229,7 +229,7 @@ metaCompileWith identifier compiler = RulesM $ do
229 let -- Set the correct group on the identifier
229 let -- Set the correct group on the identifier
230 id' = setGroup group' identifier
230 id' = setGroup group' identifier
231 -- Function to box an item into a rule
231 -- Function to box an item into a rule
232− makeRule = MetaCompileRule . map (second box)
232+ makeRule = MetaCompileRule . map (castIdentifier *** box)
233 -- Entire boxing function
233 -- Entire boxing function
234 box = (>>> fromDependency id' >>^ CompileRule . compiledItem)
234 box = (>>> fromDependency id' >>^ CompileRule . compiledItem)
235 -- Resulting compiler list
235 -- Resulting compiler list
src/Hakyll/Core/Rules/Internal.hs+2−2
@@ -35,7 +35,7 @@ import Hakyll.Core.CompiledItem
35-- added to the runtime if possible, since other items might depend upon them.
35-- added to the runtime if possible, since other items might depend upon them.
36--
36--
37data CompileRule = CompileRule CompiledItem
37data CompileRule = CompileRule CompiledItem
38− | MetaCompileRule [(Identifier, Compiler () CompileRule)]
38+ | MetaCompileRule [(Identifier (), Compiler () CompileRule)]
39
39
40-- | A collection of rules for the compilation process
40-- | A collection of rules for the compilation process
41--
41--
@@ -43,7 +43,7 @@ data RuleSet = RuleSet
43 { -- | Routes used in the compilation structure
43 { -- | Routes used in the compilation structure
44 rulesRoutes :: Routes
44 rulesRoutes :: Routes
45 , -- | Compilation rules
45 , -- | Compilation rules
46− rulesCompilers :: [(Identifier, Compiler () CompileRule)]
46+ rulesCompilers :: [(Identifier (), Compiler () CompileRule)]
47 , -- | A list of the used resources
47 , -- | A list of the used resources
48 rulesResources :: Set Resource
48 rulesResources :: Set Resource
49 }
49 }
src/Hakyll/Core/Run.hs+5−5
@@ -89,8 +89,8 @@ data RuntimeEnvironment = RuntimeEnvironment
89 }
89 }
90
90
91data RuntimeState = RuntimeState
91data RuntimeState = RuntimeState
92− { hakyllAnalyzer :: DependencyAnalyzer Identifier
92+ { hakyllAnalyzer :: DependencyAnalyzer (Identifier ())
93− , hakyllCompilers :: Map Identifier (Compiler () CompileRule)
93+ , hakyllCompilers :: Map (Identifier ()) (Compiler () CompileRule)
94 }
94 }
95
95
96newtype Runtime a = Runtime
96newtype Runtime a = Runtime
@@ -99,7 +99,7 @@ newtype Runtime a = Runtime
99
99
100-- | Add a number of compilers and continue using these compilers
100-- | Add a number of compilers and continue using these compilers
101--
101--
102−addNewCompilers :: [(Identifier, Compiler () CompileRule)]
102+addNewCompilers :: [(Identifier (), Compiler () CompileRule)]
103 -- ^ Compilers to add
103 -- ^ Compilers to add
104 -> Runtime ()
104 -> Runtime ()
105addNewCompilers newCompilers = Runtime $ do
105addNewCompilers newCompilers = Runtime $ do
@@ -157,14 +157,14 @@ stepAnalyzer = Runtime $ do
157
157
158-- | Dump cyclic error and quit
158-- | Dump cyclic error and quit
159--
159--
160−dumpCycle :: [Identifier] -> Runtime ()
160+dumpCycle :: [Identifier ()] -> Runtime ()
161dumpCycle cycle' = Runtime $ do
161dumpCycle cycle' = Runtime $ do
162 logger <- hakyllLogger <$> ask
162 logger <- hakyllLogger <$> ask
163 section logger "Dependency cycle detected! Conflict:"
163 section logger "Dependency cycle detected! Conflict:"
164 forM_ (zip cycle' $ drop 1 cycle') $ \(x, y) ->
164 forM_ (zip cycle' $ drop 1 cycle') $ \(x, y) ->
165 report logger $ show x ++ " -> " ++ show y
165 report logger $ show x ++ " -> " ++ show y
166
166
167−build :: Identifier -> Runtime ()
167+build :: Identifier () -> Runtime ()
168build id' = Runtime $ do
168build id' = Runtime $ do
169 logger <- hakyllLogger <$> ask
169 logger <- hakyllLogger <$> ask
170 routes <- hakyllRoutes <$> ask
170 routes <- hakyllRoutes <$> ask
src/Hakyll/Core/Store.hs+3−3
@@ -60,7 +60,7 @@ addToMap store path value =
60
60
61-- | Create a path
61-- | Create a path
62--
62--
63−makePath :: Store -> String -> Identifier -> FilePath
63+makePath :: Store -> String -> Identifier a -> FilePath
64makePath store name identifier = storeDirectory store </> name
64makePath store name identifier = storeDirectory store </> name
65 </> group </> toFilePath identifier </> "hakyllstore"
65 </> group </> toFilePath identifier </> "hakyllstore"
66 where
66 where
@@ -69,7 +69,7 @@ makePath store name identifier = storeDirectory store </> name
69-- | Store an item
69-- | Store an item
70--
70--
71storeSet :: (Binary a, Typeable a)
71storeSet :: (Binary a, Typeable a)
72− => Store -> String -> Identifier -> a -> IO ()
72+ => Store -> String -> Identifier a -> a -> IO ()
73storeSet store name identifier value = do
73storeSet store name identifier value = do
74 makeDirectories path
74 makeDirectories path
75 encodeFile path value
75 encodeFile path value
@@ -80,7 +80,7 @@ storeSet store name identifier value = do
80-- | Load an item
80-- | Load an item
81--
81--
82storeGet :: forall a. (Binary a, Typeable a)
82storeGet :: forall a. (Binary a, Typeable a)
83− => Store -> String -> Identifier -> IO (StoreGet a)
83+ => Store -> String -> Identifier a -> IO (StoreGet a)
84storeGet store name identifier = do
84storeGet store name identifier = do
85 -- First check the in-memory map
85 -- First check the in-memory map
86 map' <- readMVar $ storeMap store
86 map' <- readMVar $ storeMap store
src/Hakyll/Core/Writable.hs+2−2
@@ -38,5 +38,5 @@ instance Writable [Word8] where
38instance Writable Html where
38instance Writable Html where
39 write p html = write p $ renderHtml html
39 write p html = write p $ renderHtml html
40
40
41−instance Writable Identifier where
41+instance Writable (Identifier a) where
42− write p i = write p $ show i
42+ write p = write p . show
src/Hakyll/Web/Pandoc.hs+9−9
@@ -33,19 +33,19 @@ import Hakyll.Web.Page.Internal
33
33
34-- | Read a string using pandoc, with the default options
34-- | Read a string using pandoc, with the default options
35--
35--
36−readPandoc :: FileType -- ^ File type, determines how parsing happens
36+readPandoc :: FileType -- ^ Determines how parsing happens
37− -> Maybe Identifier -- ^ Optional, for better error messages
37+ -> Maybe (Identifier a) -- ^ Optional, for better error messages
38− -> String -- ^ String to read
38+ -> String -- ^ String to read
39− -> Pandoc -- ^ Resulting document
39+ -> Pandoc -- ^ Resulting document
40readPandoc = readPandocWith defaultHakyllParserState
40readPandoc = readPandocWith defaultHakyllParserState
41
41
42-- | Read a string using pandoc, with the supplied options
42-- | Read a string using pandoc, with the supplied options
43--
43--
44−readPandocWith :: ParserState -- ^ Parser options
44+readPandocWith :: ParserState -- ^ Parser options
45− -> FileType -- ^ File type, determines parsing method
45+ -> FileType -- ^ Determines parsing method
46− -> Maybe Identifier -- ^ Optional, for better error messages
46+ -> Maybe (Identifier a) -- ^ Optional, for better error messages
47− -> String -- ^ String to read
47+ -> String -- ^ String to read
48− -> Pandoc -- ^ Resulting document
48+ -> Pandoc -- ^ Resulting document
49readPandocWith state fileType' id' = case fileType' of
49readPandocWith state fileType' id' = case fileType' of
50 Html -> readHtml state
50 Html -> readHtml state
51 LaTeX -> readLaTeX state
51 LaTeX -> readLaTeX state
src/Hakyll/Web/Tags.hs+6−6
@@ -111,7 +111,7 @@ readCategory = readTagsWith getCategory
111
111
112-- | Render tags in HTML
112-- | Render tags in HTML
113--
113--
114−renderTags :: (String -> Identifier)
114+renderTags :: (String -> Identifier a)
115 -- ^ Produce a link
115 -- ^ Produce a link
116 -> (String -> String -> Int -> Int -> Int -> String)
116 -> (String -> String -> Int -> Int -> Int -> String)
117 -- ^ Produce a tag item: tag, url, count, min count, max count
117 -- ^ Produce a tag item: tag, url, count, min count, max count
@@ -141,7 +141,7 @@ renderTags makeUrl makeItem concatItems = proc (Tags tags) -> do
141
141
142-- | Render a tag cloud in HTML
142-- | Render a tag cloud in HTML
143--
143--
144−renderTagCloud :: (String -> Identifier) -- ^ Produce a link for a tag
144+renderTagCloud :: (String -> Identifier a) -- ^ Produce a link for a tag
145 -> Double -- ^ Smallest font size, in percent
145 -> Double -- ^ Smallest font size, in percent
146 -> Double -- ^ Biggest font size, in percent
146 -> Double -- ^ Biggest font size, in percent
147 -> Compiler (Tags a) String -- ^ Tag cloud renderer
147 -> Compiler (Tags a) String -- ^ Tag cloud renderer
@@ -162,7 +162,7 @@ renderTagCloud makeUrl minSize maxSize =
162
162
163-- | Render a simple tag list in HTML, with the tag count next to the item
163-- | Render a simple tag list in HTML, with the tag count next to the item
164--
164--
165−renderTagList :: (String -> Identifier) -> Compiler (Tags a) (String)
165+renderTagList :: (String -> Identifier a) -> Compiler (Tags a) (String)
166renderTagList makeUrl = renderTags makeUrl makeLink (intercalate ", ")
166renderTagList makeUrl = renderTags makeUrl makeLink (intercalate ", ")
167 where
167 where
168 makeLink tag url count _ _ = renderHtml $
168 makeLink tag url count _ _ = renderHtml $
@@ -172,7 +172,7 @@ renderTagList makeUrl = renderTags makeUrl makeLink (intercalate ", ")
172--
172--
173renderTagsFieldWith :: (Page a -> [String]) -- ^ Function to get the tags
173renderTagsFieldWith :: (Page a -> [String]) -- ^ Function to get the tags
174 -> String -- ^ Destination key
174 -> String -- ^ Destination key
175− -> (String -> Identifier) -- ^ Create a link for a tag
175+ -> (String -> Identifier a) -- ^ Create a link for a tag
176 -> Compiler (Page a) (Page a) -- ^ Resulting compiler
176 -> Compiler (Page a) (Page a) -- ^ Resulting compiler
177renderTagsFieldWith tags destination makeUrl =
177renderTagsFieldWith tags destination makeUrl =
178 id &&& arr tags >>> setFieldA destination renderTags'
178 id &&& arr tags >>> setFieldA destination renderTags'
@@ -192,13 +192,13 @@ renderTagsFieldWith tags destination makeUrl =
192-- | Render tags with links
192-- | Render tags with links
193--
193--
194renderTagsField :: String -- ^ Destination key
194renderTagsField :: String -- ^ Destination key
195− -> (String -> Identifier) -- ^ Create a link for a tag
195+ -> (String -> Identifier a) -- ^ Create a link for a tag
196 -> Compiler (Page a) (Page a) -- ^ Resulting compiler
196 -> Compiler (Page a) (Page a) -- ^ Resulting compiler
197renderTagsField = renderTagsFieldWith getTags
197renderTagsField = renderTagsFieldWith getTags
198
198
199-- | Render the category in a link
199-- | Render the category in a link
200--
200--
201renderCategoryField :: String -- ^ Destination key
201renderCategoryField :: String -- ^ Destination key
202− -> (String -> Identifier) -- ^ Create a category link
202+ -> (String -> Identifier a) -- ^ Create a category link
203 -> Compiler (Page a) (Page a) -- ^ Resulting compiler
203 -> Compiler (Page a) (Page a) -- ^ Resulting compiler
204renderCategoryField = renderTagsFieldWith getCategory
204renderCategoryField = renderTagsFieldWith getCategory
src/Hakyll/Web/Template.hs+1−1
@@ -104,6 +104,6 @@ templateCompilerWith settings =
104 -- Hakyll template
104 -- Hakyll template
105 else readTemplate string
105 else readTemplate string
106
106
107−applyTemplateCompiler :: Identifier -- ^ Template
107+applyTemplateCompiler :: Identifier Template -- ^ Template
108 -> Compiler (Page String) (Page String) -- ^ Compiler
108 -> Compiler (Page String) (Page String) -- ^ Compiler
109applyTemplateCompiler identifier = require identifier (flip applyTemplate)
109applyTemplateCompiler identifier = require identifier (flip applyTemplate)