From ad6712121ffc3e41f6bd2a9833267252315b6f65 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Thu, 23 Dec 2010 14:31:45 +0100 Subject: Add directed graph modules --- src/Hakyll/Core/DirectedGraph/DependencySolver.hs | 68 +++++++++++++++++++++++ src/Hakyll/Core/DirectedGraph/Internal.hs | 39 +++++++++++++ src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs | 25 +++++++++ 3 files changed, 132 insertions(+) create mode 100644 src/Hakyll/Core/DirectedGraph/DependencySolver.hs create mode 100644 src/Hakyll/Core/DirectedGraph/Internal.hs create mode 100644 src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs (limited to 'src/Hakyll/Core/DirectedGraph') diff --git a/src/Hakyll/Core/DirectedGraph/DependencySolver.hs b/src/Hakyll/Core/DirectedGraph/DependencySolver.hs new file mode 100644 index 0000000..dce59e0 --- /dev/null +++ b/src/Hakyll/Core/DirectedGraph/DependencySolver.hs @@ -0,0 +1,68 @@ +-- | Given a dependency graph, this module provides a function that will +-- generate an order in which the graph can be visited, so that all the +-- dependencies of a given node have been visited before the node itself is +-- visited. +-- +module Hakyll.Core.DirectedGraph.DependencySolver + ( solveDependencies + ) where + +import Prelude +import qualified Prelude as P +import Data.Set (Set) +import Data.Maybe (catMaybes) +import qualified Data.Map as M +import qualified Data.Set as S + +import Hakyll.Core.DirectedGraph +import qualified Hakyll.Core.DirectedGraph as DG +import Hakyll.Core.DirectedGraph.Internal + +-- | Solve a dependency graph. This function returns an order to run the +-- different nodes +-- +solveDependencies :: Ord a + => DirectedGraph a -- ^ Graph + -> [a] -- ^ Resulting plan +solveDependencies = P.reverse . order [] [] S.empty + +-- | Produce a reversed order using a stack +-- +order :: Ord a + => [a] -- ^ Temporary result + -> [Node a] -- ^ Backtrace stack + -> Set a -- ^ Items in the stack + -> DirectedGraph a -- ^ Graph + -> [a] -- ^ Ordered result +order temp stack set graph@(DirectedGraph graph') + -- Empty graph - return our current result + | M.null graph' = temp + | otherwise = case stack of + + -- Empty stack - pick a node, and add it to the stack + [] -> + let (tag, node) = M.findMin graph' + in order temp (node : stack) (S.insert tag set) graph + + -- At least one item on the stack - continue using this item + (node : stackTail) -> + -- Check which dependencies are still in the graph + let tag = nodeTag node + deps = S.toList $ nodeNeighbours node + unsatisfied = catMaybes $ map (flip M.lookup graph') deps + in case unsatisfied of + + -- All dependencies for node are satisfied, we can return it and + -- remove it from the graph + [] -> order (tag : temp) stackTail (S.delete tag set) + (DG.filter (== tag) graph) + + -- There is at least one dependency left. We need to solve that + -- one first... + (dep : _) -> if (nodeTag dep) `S.member` set + -- The dependency is already in our stack - cycle detected! + then error "order: Cycle detected!" -- TODO: Dump cycle + -- Continue with the dependency + else order temp (dep : node : stackTail) + (S.insert (nodeTag dep) set) + graph diff --git a/src/Hakyll/Core/DirectedGraph/Internal.hs b/src/Hakyll/Core/DirectedGraph/Internal.hs new file mode 100644 index 0000000..9890fc0 --- /dev/null +++ b/src/Hakyll/Core/DirectedGraph/Internal.hs @@ -0,0 +1,39 @@ +-- | Internal structure of the DirectedGraph type. Not exported in the library. +-- +module Hakyll.Core.DirectedGraph.Internal + ( Node (..) + , DirectedGraph (..) + ) where + +import Prelude hiding (reverse, filter) +import Data.Monoid (Monoid, mempty, mappend) +import Data.Set (Set) +import Data.Map (Map) +import qualified Data.Map as M +import qualified Data.Set as S + +-- | A node in the directed graph +-- +data Node a = Node + { nodeTag :: a -- ^ Tag identifying the node + , nodeNeighbours :: (Set a) -- ^ Edges starting at this node + } deriving (Show) + +-- | Append two nodes. Useful for joining graphs. +-- +appendNodes :: Ord a => Node a -> Node a -> Node a +appendNodes (Node t1 n1) (Node t2 n2) + | t1 /= t2 = error "appendNodes: Appending differently tagged nodes" + | otherwise = Node t1 (n1 `S.union` n2) + +-- | Type used to represent a directed graph +-- +newtype DirectedGraph a = DirectedGraph {unDirectedGraph :: Map a (Node a)} + deriving (Show) + +-- | Allow users to concatenate different graphs +-- +instance Ord a => Monoid (DirectedGraph a) where + mempty = DirectedGraph M.empty + mappend (DirectedGraph m1) (DirectedGraph m2) = DirectedGraph $ + M.unionWith appendNodes m1 m2 diff --git a/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs b/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs new file mode 100644 index 0000000..a3bc57a --- /dev/null +++ b/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs @@ -0,0 +1,25 @@ +-- | Module exporting a function that works as a filter on a dependency graph. +-- Given a list of obsolete nodes, this filter will reduce the graph so it only +-- contains obsolete nodes and nodes that depend (directly or indirectly) on +-- obsolete nodes. +-- +module Hakyll.Core.DirectedGraph.ObsoleteFilter + ( obsoleteFilter + ) where + +import qualified Data.Set as S + +import Hakyll.Core.DirectedGraph +import qualified Hakyll.Core.DirectedGraph as DG + +-- | Given a list of obsolete items, filter the dependency graph so it only +-- contains these items +-- +obsoleteFilter :: Ord a + => [a] -- ^ List of obsolete items + -> DirectedGraph a -- ^ Dependency graph + -> DirectedGraph a -- ^ Resulting dependency graph +obsoleteFilter obsolete graph = + let reversed = DG.reverse graph + allObsolete = S.unions $ map (flip reachableNodes reversed) obsolete + in DG.filter (`S.member` allObsolete) graph -- cgit v1.2.3 From d1d28b9349549297f89ade80616eb7b14083e600 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Thu, 23 Dec 2010 14:51:38 +0100 Subject: Add tests for the directed graph modules --- src/Hakyll/Core/DirectedGraph.hs | 27 ++++--------- src/Hakyll/Core/DirectedGraph/DependencySolver.hs | 3 +- src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs | 6 +-- tests/Hakyll/Core/DirectedGraph/Tests.hs | 48 +++++++++++++++++++++++ tests/TestSuite.hs | 11 ++++++ 5 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 tests/Hakyll/Core/DirectedGraph/Tests.hs create mode 100644 tests/TestSuite.hs (limited to 'src/Hakyll/Core/DirectedGraph') diff --git a/src/Hakyll/Core/DirectedGraph.hs b/src/Hakyll/Core/DirectedGraph.hs index 6dc6ae5..b24ce25 100644 --- a/src/Hakyll/Core/DirectedGraph.hs +++ b/src/Hakyll/Core/DirectedGraph.hs @@ -4,6 +4,7 @@ module Hakyll.Core.DirectedGraph ( DirectedGraph , fromList + , nodes , neighbours , reverse , filter @@ -26,6 +27,13 @@ fromList :: Ord a -> DirectedGraph a -- ^ Resulting directed graph fromList = DirectedGraph . M.fromList . map (\(t, d) -> (t, Node t d)) +-- | Get all nodes in the graph +-- +nodes :: Ord a + => DirectedGraph a -- ^ Graph to get the nodes from + -> Set a -- ^ All nodes in the graph +nodes = M.keysSet . unDirectedGraph + -- | Get a set of reachable neighbours from a directed graph -- neighbours :: Ord a @@ -66,22 +74,3 @@ reachableNodes x graph = reachable (neighbours x graph) (S.singleton x) sanitize = S.filter (`S.notMember` visited) neighbours' = S.unions $ map (flip neighbours graph) $ S.toList $ sanitize next - -{- -exampleGraph :: DirectedGraph Int -exampleGraph = fromList - [ makeNode 8 [2, 4, 6] - , makeNode 2 [4, 3] - , makeNode 4 [3] - , makeNode 6 [4] - , makeNode 3 [] - ] - where - makeNode tag deps = (tag, S.fromList deps) - -cyclic :: DirectedGraph Int -cyclic = fromList - [ (1, S.fromList [2]) - , (2, S.fromList [1, 3]) - ] --} diff --git a/src/Hakyll/Core/DirectedGraph/DependencySolver.hs b/src/Hakyll/Core/DirectedGraph/DependencySolver.hs index dce59e0..17a4b69 100644 --- a/src/Hakyll/Core/DirectedGraph/DependencySolver.hs +++ b/src/Hakyll/Core/DirectedGraph/DependencySolver.hs @@ -15,7 +15,6 @@ import qualified Data.Map as M import qualified Data.Set as S import Hakyll.Core.DirectedGraph -import qualified Hakyll.Core.DirectedGraph as DG import Hakyll.Core.DirectedGraph.Internal -- | Solve a dependency graph. This function returns an order to run the @@ -55,7 +54,7 @@ order temp stack set graph@(DirectedGraph graph') -- All dependencies for node are satisfied, we can return it and -- remove it from the graph [] -> order (tag : temp) stackTail (S.delete tag set) - (DG.filter (== tag) graph) + (DirectedGraph $ M.delete tag graph') -- There is at least one dependency left. We need to solve that -- one first... diff --git a/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs b/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs index a3bc57a..f781819 100644 --- a/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs +++ b/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs @@ -4,7 +4,7 @@ -- obsolete nodes. -- module Hakyll.Core.DirectedGraph.ObsoleteFilter - ( obsoleteFilter + ( filterObsolete ) where import qualified Data.Set as S @@ -15,11 +15,11 @@ import qualified Hakyll.Core.DirectedGraph as DG -- | Given a list of obsolete items, filter the dependency graph so it only -- contains these items -- -obsoleteFilter :: Ord a +filterObsolete :: Ord a => [a] -- ^ List of obsolete items -> DirectedGraph a -- ^ Dependency graph -> DirectedGraph a -- ^ Resulting dependency graph -obsoleteFilter obsolete graph = +filterObsolete obsolete graph = let reversed = DG.reverse graph allObsolete = S.unions $ map (flip reachableNodes reversed) obsolete in DG.filter (`S.member` allObsolete) graph diff --git a/tests/Hakyll/Core/DirectedGraph/Tests.hs b/tests/Hakyll/Core/DirectedGraph/Tests.hs new file mode 100644 index 0000000..4ce5944 --- /dev/null +++ b/tests/Hakyll/Core/DirectedGraph/Tests.hs @@ -0,0 +1,48 @@ +module Hakyll.Core.DirectedGraph.Tests + ( tests + ) where + +import Data.Set (Set) +import qualified Data.Set as S + +import Test.Framework +import Test.Framework.Providers.HUnit +import Test.HUnit hiding (Test) + +import Hakyll.Core.DirectedGraph +import Hakyll.Core.DirectedGraph.DependencySolver +import Hakyll.Core.DirectedGraph.ObsoleteFilter + +tests :: [Test] +tests = + [ testCase "solveDependencies01" solveDependencies01 + , testCase "filterObsolete01" filterObsolete01 + , testCase "filterObsolete02" filterObsolete02 + ] + +node :: Ord a => a -> [a] -> (a, Set a) +node t n = (t, S.fromList n) + +testGraph01 :: DirectedGraph Int +testGraph01 = fromList + [ node 8 [2, 4, 6] + , node 2 [4, 3] + , node 4 [3] + , node 6 [4] + , node 3 [] + ] + +solveDependencies01 :: Assertion +solveDependencies01 = result == [3, 4, 2, 6, 8] || result == [3, 4, 2, 6, 8] + @? "solveDependencies01" + where + result = solveDependencies testGraph01 + +filterObsolete01 :: Assertion +filterObsolete01 = nodes (filterObsolete [6] testGraph01) == S.fromList [6, 8] + @? "filterObsolete01" + +filterObsolete02 :: Assertion +filterObsolete02 = + nodes (filterObsolete [4] testGraph01) == S.fromList [4, 2, 6, 8] + @? "filterObsolete02" diff --git a/tests/TestSuite.hs b/tests/TestSuite.hs new file mode 100644 index 0000000..26b26f0 --- /dev/null +++ b/tests/TestSuite.hs @@ -0,0 +1,11 @@ +module TestSuite where + +import Test.Framework (defaultMain, testGroup) + +import qualified Hakyll.Core.DirectedGraph.Tests + +main :: IO () +main = defaultMain + [ testGroup "Hakyll.Core.DirectedGraph.Tests" + Hakyll.Core.DirectedGraph.Tests.tests + ] -- cgit v1.2.3 From 12c446785c76130a65c46cc603e767893b4818b5 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Fri, 24 Dec 2010 16:55:20 +0100 Subject: Add target module --- src/Hakyll/Core/DirectedGraph/Internal.hs | 3 +- src/Hakyll/Core/Target.hs | 11 ++++++++ src/Hakyll/Core/Target/Internal.hs | 46 +++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/Hakyll/Core/Target.hs create mode 100644 src/Hakyll/Core/Target/Internal.hs (limited to 'src/Hakyll/Core/DirectedGraph') diff --git a/src/Hakyll/Core/DirectedGraph/Internal.hs b/src/Hakyll/Core/DirectedGraph/Internal.hs index 9890fc0..52a712d 100644 --- a/src/Hakyll/Core/DirectedGraph/Internal.hs +++ b/src/Hakyll/Core/DirectedGraph/Internal.hs @@ -1,4 +1,5 @@ --- | Internal structure of the DirectedGraph type. Not exported in the library. +-- | Internal structure of the DirectedGraph type. Not exported outside of the +-- library. -- module Hakyll.Core.DirectedGraph.Internal ( Node (..) diff --git a/src/Hakyll/Core/Target.hs b/src/Hakyll/Core/Target.hs new file mode 100644 index 0000000..1f783df --- /dev/null +++ b/src/Hakyll/Core/Target.hs @@ -0,0 +1,11 @@ +-- | A target represents one compilation unit, e.g. a blog post, a CSS file... +-- +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +module Hakyll.Core.Target + ( DependencyLookup + , TargetM + , Target + , runTarget + ) where + +import Hakyll.Core.Target.Internal diff --git a/src/Hakyll/Core/Target/Internal.hs b/src/Hakyll/Core/Target/Internal.hs new file mode 100644 index 0000000..a58f736 --- /dev/null +++ b/src/Hakyll/Core/Target/Internal.hs @@ -0,0 +1,46 @@ +-- | Internal structure of a Target, not exported outside of the library +-- +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +module Hakyll.Core.Target.Internal + ( DependencyLookup + , TargetM (..) + , Target + , runTarget + ) where + +import Control.Monad.Trans (MonadIO) +import Control.Monad.Reader (ReaderT, runReaderT) + +import Hakyll.Core.Identifier + +-- | A lookup with which we can get dependencies +-- +type DependencyLookup a = Identifier -> a + +-- | Environment for the target monad +-- +data TargetEnvironment a = TargetEnvironment + { targetIdentifier :: Identifier + , targetDependencyLookup :: DependencyLookup a -- ^ Dependency lookup + } + +-- | Monad for targets. In this monad, the user can compose targets and describe +-- how they should be created. +-- +newtype TargetM a b = TargetM {unTargetM :: ReaderT (TargetEnvironment a) IO b} + deriving (Monad, Functor, MonadIO) + +-- | Simplification of the 'TargetM' type for concrete cases: the type of the +-- returned item should equal the type of the dependencies. +-- +type Target a = TargetM a a + +-- | Run a target, yielding an actual result. +-- +runTarget :: Target a -> Identifier -> DependencyLookup a -> IO a +runTarget target id' lookup' = runReaderT (unTargetM target) env + where + env = TargetEnvironment + { targetIdentifier = id' + , targetDependencyLookup = lookup' + } -- cgit v1.2.3 From 5bc8028696ae8d5aa2c60db87aea3d00f9d7aebd Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Sun, 26 Dec 2010 00:09:35 +0100 Subject: Add DirectedGraph to DOT module --- src/Hakyll/Core/DirectedGraph/Dot.hs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/Hakyll/Core/DirectedGraph/Dot.hs (limited to 'src/Hakyll/Core/DirectedGraph') diff --git a/src/Hakyll/Core/DirectedGraph/Dot.hs b/src/Hakyll/Core/DirectedGraph/Dot.hs new file mode 100644 index 0000000..8289992 --- /dev/null +++ b/src/Hakyll/Core/DirectedGraph/Dot.hs @@ -0,0 +1,30 @@ +-- | Dump a directed graph in dot format. Used for debugging purposes +-- +module Hakyll.Core.DirectedGraph.Dot + ( toDot + , writeDot + ) where + +import Hakyll.Core.DirectedGraph +import qualified Data.Set as S + +-- | Convert a directed graph into dot format for debugging purposes +-- +toDot :: Ord a + => (a -> String) -- ^ Convert nodes to dot names + -> DirectedGraph a -- ^ Graph to dump + -> String -- ^ Resulting string +toDot showTag graph = unlines $ concat + [ return "digraph dependencies {" + , concatMap showNode (S.toList $ nodes graph) + , return "}" + ] + where + showNode node = map (showEdge node) $ S.toList $ neighbours node graph + showEdge x y = " \"" ++ showTag x ++ "\" -> \"" ++ showTag y ++ "\";" + +-- | Write out the @.dot@ file to a given file path. See 'toDot' for more +-- information. +-- +writeDot :: Ord a => FilePath -> (a -> String) -> DirectedGraph a -> IO () +writeDot path showTag = writeFile path . toDot showTag -- cgit v1.2.3 From 2ceb5f59d0728c380ad7b4f319a9282741e715b9 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Mon, 3 Jan 2011 22:13:04 +0100 Subject: Avoid looking at up-to-date items at all --- src/Hakyll/Core/CompiledItem.hs | 2 +- src/Hakyll/Core/Compiler.hs | 34 ++++++++++++--- src/Hakyll/Core/Compiler/Internal.hs | 2 +- src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs | 6 ++- src/Hakyll/Core/Run.hs | 58 +++++++++++++++++-------- 5 files changed, 74 insertions(+), 28 deletions(-) (limited to 'src/Hakyll/Core/DirectedGraph') diff --git a/src/Hakyll/Core/CompiledItem.hs b/src/Hakyll/Core/CompiledItem.hs index d191e2a..d12d172 100644 --- a/src/Hakyll/Core/CompiledItem.hs +++ b/src/Hakyll/Core/CompiledItem.hs @@ -4,7 +4,7 @@ -- {-# LANGUAGE ExistentialQuantification #-} module Hakyll.Core.CompiledItem - ( CompiledItem + ( CompiledItem (..) , compiledItem , unCompiledItem ) where diff --git a/src/Hakyll/Core/Compiler.hs b/src/Hakyll/Core/Compiler.hs index fdc7d20..df1caeb 100644 --- a/src/Hakyll/Core/Compiler.hs +++ b/src/Hakyll/Core/Compiler.hs @@ -6,6 +6,7 @@ module Hakyll.Core.Compiler , getIdentifier , getRoute , getResourceString + , storeResult , require , requireAll , cached @@ -17,6 +18,7 @@ import Control.Applicative ((<$>)) import Control.Monad.Reader (ask) import Control.Monad.Trans (liftIO) import Control.Category (Category, (.)) +import Data.Maybe (fromMaybe) import Data.Binary (Binary) import Data.Typeable (Typeable) @@ -48,6 +50,28 @@ getResourceString = getIdentifier >>> getResourceString' provider <- compilerResourceProvider <$> ask liftIO $ resourceString provider id' +-- | Store a finished item in the cache +-- +storeResult :: Store -> Identifier -> CompiledItem -> IO () +storeResult store identifier (CompiledItem x) = + storeSet store "Hakyll.Core.Compiler.storeResult" identifier x + +-- | Auxiliary: get a dependency +-- +getDependencyOrResult :: (Binary a, Writable a, Typeable a) + => Identifier -> CompilerM a +getDependencyOrResult identifier = CompilerM $ do + lookup' <- compilerDependencyLookup <$> ask + store <- compilerStore <$> ask + case lookup' identifier of + -- Found in the dependency lookup + Just r -> return $ unCompiledItem r + -- Not found here, try the main cache + Nothing -> fmap (fromMaybe error') $ liftIO $ + storeGet store "Hakyll.Core.Compiler.storeResult" identifier + where + error' = error "Hakyll.Core.Compiler.getDependency: Not found" + -- | Require another target. Using this function ensures automatic handling of -- dependencies -- @@ -58,9 +82,9 @@ require :: (Binary a, Typeable a, Writable a) require identifier f = fromDependencies (const [identifier]) >>> fromJob require' where - require' x = CompilerM $ do - lookup' <- compilerDependencyLookup <$> ask - return $ f x $ unCompiledItem $ lookup' identifier + require' x = do + y <- getDependencyOrResult identifier + return $ f x y -- | Require a number of targets. Using this function ensures automatic handling -- of dependencies @@ -75,8 +99,8 @@ requireAll pattern f = getDeps = matches pattern . resourceList requireAll' x = CompilerM $ do deps <- getDeps . compilerResourceProvider <$> ask - lookup' <- compilerDependencyLookup <$> ask - return $ f x $ map (unCompiledItem . lookup') deps + items <- mapM (unCompilerM . getDependencyOrResult) deps + return $ f x items cached :: (Binary a) => String diff --git a/src/Hakyll/Core/Compiler/Internal.hs b/src/Hakyll/Core/Compiler/Internal.hs index a4dd695..262cda0 100644 --- a/src/Hakyll/Core/Compiler/Internal.hs +++ b/src/Hakyll/Core/Compiler/Internal.hs @@ -32,7 +32,7 @@ type Dependencies = Set Identifier -- | A lookup with which we can get dependencies -- -type DependencyLookup = Identifier -> CompiledItem +type DependencyLookup = Identifier -> Maybe CompiledItem -- | Environment in which a compiler runs -- diff --git a/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs b/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs index f781819..9aeb2ff 100644 --- a/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs +++ b/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs @@ -7,6 +7,7 @@ module Hakyll.Core.DirectedGraph.ObsoleteFilter ( filterObsolete ) where +import Data.Set (Set) import qualified Data.Set as S import Hakyll.Core.DirectedGraph @@ -16,10 +17,11 @@ import qualified Hakyll.Core.DirectedGraph as DG -- contains these items -- filterObsolete :: Ord a - => [a] -- ^ List of obsolete items + => Set a -- ^ Obsolete items -> DirectedGraph a -- ^ Dependency graph -> DirectedGraph a -- ^ Resulting dependency graph filterObsolete obsolete graph = let reversed = DG.reverse graph - allObsolete = S.unions $ map (flip reachableNodes reversed) obsolete + allObsolete = S.unions $ map (flip reachableNodes reversed) + $ S.toList obsolete in DG.filter (`S.member` allObsolete) graph diff --git a/src/Hakyll/Core/Run.hs b/src/Hakyll/Core/Run.hs index 6898b3a..e9ec47e 100644 --- a/src/Hakyll/Core/Run.hs +++ b/src/Hakyll/Core/Run.hs @@ -3,13 +3,16 @@ module Hakyll.Core.Run where import Control.Arrow ((&&&)) -import Control.Monad (foldM, forM_, forM) +import Control.Monad (foldM, forM_, forM, filterM) +import Data.Map (Map) import qualified Data.Map as M import Data.Monoid (mempty) import Data.Typeable (Typeable) import Data.Binary (Binary) import System.FilePath (()) import Control.Applicative ((<$>)) +import Data.Set (Set) +import qualified Data.Set as S import Hakyll.Core.Route import Hakyll.Core.Identifier @@ -22,6 +25,7 @@ import Hakyll.Core.Rules import Hakyll.Core.DirectedGraph import Hakyll.Core.DirectedGraph.Dot import Hakyll.Core.DirectedGraph.DependencySolver +import Hakyll.Core.DirectedGraph.ObsoleteFilter import Hakyll.Core.Writable import Hakyll.Core.Store import Hakyll.Core.CompiledItem @@ -48,9 +52,23 @@ hakyllWith rules provider store = do -- Create a compiler map compilerMap = M.fromList compilers - -- Create and solve the graph, creating a compiler order + -- Create the graph graph = fromList dependencies - ordered = solveDependencies graph + + putStrLn "Writing dependency graph to dependencies.dot..." + writeDot "dependencies.dot" show graph + + -- Check which items are up-to-date + modified' <- modified provider store $ map fst compilers + + let -- Try to reduce the graph + reducedGraph = filterObsolete modified' graph + + putStrLn "Writing reduced graph to reduced.dot..." + writeDot "reduced.dot" show reducedGraph + + let -- Solve the graph + ordered = solveDependencies reducedGraph -- Join the order with the compilers again orderedCompilers = map (id &&& (compilerMap M.!)) ordered @@ -58,30 +76,23 @@ hakyllWith rules provider store = do -- Fetch the routes route' = rulesRoute ruleSet - putStrLn "Writing dependency graph to dependencies.dot..." - writeDot "dependencies.dot" show graph - - -- Check which items are up-to-date: modified will be a Map Identifier Bool - modifiedMap <- fmap M.fromList $ forM orderedCompilers $ \(id', _) -> do - modified <- if resourceExists provider id' - then resourceModified provider id' store - else return False - return (id', modified) + putStrLn $ show reducedGraph + putStrLn $ show ordered -- Generate all the targets in order - _ <- foldM (addTarget route' modifiedMap) M.empty orderedCompilers + _ <- foldM (addTarget route' modified') M.empty orderedCompilers putStrLn "DONE." where - addTarget route' modifiedMap map' (id', comp) = do + addTarget route' modified' map' (id', comp) = do let url = runRoute route' id' -- Check if the resource was modified - let modified = modifiedMap M.! id' + let isModified = id' `S.member` modified' -- Run the compiler compiled <- runCompilerJob comp id' provider (dependencyLookup map') - url store modified + url store isModified putStrLn $ "Generated target: " ++ show id' case url of @@ -92,9 +103,18 @@ hakyllWith rules provider store = do makeDirectories path write path compiled + -- Store it in the cache + storeResult store id' compiled + putStrLn "" return $ M.insert id' compiled map' - dependencyLookup map' id' = case M.lookup id' map' of - Nothing -> error $ "dependencyLookup: " ++ show id' ++ " not found" - Just d -> d + dependencyLookup map' id' = M.lookup id' map' + +modified :: ResourceProvider -- ^ Resource provider + -> Store -- ^ Store + -> [Identifier] -- ^ Identifiers to check + -> IO (Set Identifier) -- ^ Modified resources +modified provider store ids = fmap S.fromList $ flip filterM ids $ \id' -> + if resourceExists provider id' then resourceModified provider id' store + else return False -- cgit v1.2.3 From d0939102bf26ed81b4e57dc96f44e5330913ab6f Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Fri, 7 Jan 2011 19:17:14 +0100 Subject: Metacompilers now work, todo: cleanup --- src/Hakyll/Core/Compiler.hs | 9 ++------- src/Hakyll/Core/Compiler/Internal.hs | 6 ++++++ src/Hakyll/Core/DirectedGraph.hs | 23 +++++++-------------- src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs | 27 ------------------------- src/Hakyll/Core/Rules.hs | 5 +++-- src/Hakyll/Core/Run.hs | 27 ++++++++++++++++--------- 6 files changed, 35 insertions(+), 62 deletions(-) delete mode 100644 src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs (limited to 'src/Hakyll/Core/DirectedGraph') diff --git a/src/Hakyll/Core/Compiler.hs b/src/Hakyll/Core/Compiler.hs index f754860..4c624e2 100644 --- a/src/Hakyll/Core/Compiler.hs +++ b/src/Hakyll/Core/Compiler.hs @@ -7,7 +7,7 @@ module Hakyll.Core.Compiler , getIdentifier , getRoute , getResourceString - , waitFor + , fromDependency , require , requireAll , cached @@ -92,11 +92,6 @@ getDependency identifier = CompilerM $ do ++ show identifier ++ " not found in the cache, the cache might be corrupted" --- | Wait until another compiler has finished before running this compiler --- -waitFor :: Identifier -> Compiler a a -waitFor = fromDependencies . const . return - -- | Require another target. Using this function ensures automatic handling of -- dependencies -- @@ -105,7 +100,7 @@ require :: (Binary a, Typeable a, Writable a) -> (b -> a -> c) -> Compiler b c require identifier f = - waitFor identifier >>> fromJob require' + fromDependency identifier >>> fromJob require' where require' x = do y <- getDependency identifier diff --git a/src/Hakyll/Core/Compiler/Internal.hs b/src/Hakyll/Core/Compiler/Internal.hs index 0642b85..938d81a 100644 --- a/src/Hakyll/Core/Compiler/Internal.hs +++ b/src/Hakyll/Core/Compiler/Internal.hs @@ -10,6 +10,7 @@ module Hakyll.Core.Compiler.Internal , runCompilerDependencies , fromJob , fromDependencies + , fromDependency ) where import Prelude hiding ((.), id) @@ -101,3 +102,8 @@ fromJob = Compiler (return S.empty) fromDependencies :: (ResourceProvider -> [Identifier]) -> Compiler b b fromDependencies deps = Compiler (S.fromList . deps <$> ask) return + +-- | Wait until another compiler has finished before running this compiler +-- +fromDependency :: Identifier -> Compiler a a +fromDependency = fromDependencies . const . return diff --git a/src/Hakyll/Core/DirectedGraph.hs b/src/Hakyll/Core/DirectedGraph.hs index b24ce25..bf52277 100644 --- a/src/Hakyll/Core/DirectedGraph.hs +++ b/src/Hakyll/Core/DirectedGraph.hs @@ -7,11 +7,10 @@ module Hakyll.Core.DirectedGraph , nodes , neighbours , reverse - , filter , reachableNodes ) where -import Prelude hiding (reverse, filter) +import Prelude hiding (reverse) import Data.Monoid (mconcat) import Data.Set (Set) import Data.Maybe (fromMaybe) @@ -53,24 +52,16 @@ reverse = mconcat . map reverse' . M.toList . unDirectedGraph reverse' (id', Node _ neighbours') = fromList $ zip (S.toList neighbours') $ repeat $ S.singleton id' --- | Filter a directed graph (i.e. remove nodes based on a predicate) +-- | Find all reachable nodes from a given set of nodes in the directed graph -- -filter :: Ord a - => (a -> Bool) -- ^ Predicate - -> DirectedGraph a -- ^ Graph - -> DirectedGraph a -- ^ Resulting graph -filter predicate = - DirectedGraph . M.filterWithKey (\k _ -> predicate k) . unDirectedGraph - --- | Find all reachable nodes from a given node in the directed graph --- -reachableNodes :: Ord a => a -> DirectedGraph a -> Set a -reachableNodes x graph = reachable (neighbours x graph) (S.singleton x) +reachableNodes :: Ord a => Set a -> DirectedGraph a -> Set a +reachableNodes set graph = reachable (setNeighbours set) set where reachable next visited | S.null next = visited | otherwise = reachable (sanitize neighbours') (next `S.union` visited) where sanitize = S.filter (`S.notMember` visited) - neighbours' = S.unions $ map (flip neighbours graph) - $ S.toList $ sanitize next + neighbours' = setNeighbours (sanitize next) + + setNeighbours = S.unions . map (flip neighbours graph) . S.toList diff --git a/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs b/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs deleted file mode 100644 index 9aeb2ff..0000000 --- a/src/Hakyll/Core/DirectedGraph/ObsoleteFilter.hs +++ /dev/null @@ -1,27 +0,0 @@ --- | Module exporting a function that works as a filter on a dependency graph. --- Given a list of obsolete nodes, this filter will reduce the graph so it only --- contains obsolete nodes and nodes that depend (directly or indirectly) on --- obsolete nodes. --- -module Hakyll.Core.DirectedGraph.ObsoleteFilter - ( filterObsolete - ) where - -import Data.Set (Set) -import qualified Data.Set as S - -import Hakyll.Core.DirectedGraph -import qualified Hakyll.Core.DirectedGraph as DG - --- | Given a list of obsolete items, filter the dependency graph so it only --- contains these items --- -filterObsolete :: Ord a - => Set a -- ^ Obsolete items - -> DirectedGraph a -- ^ Dependency graph - -> DirectedGraph a -- ^ Resulting dependency graph -filterObsolete obsolete graph = - let reversed = DG.reverse graph - allObsolete = S.unions $ map (flip reachableNodes reversed) - $ S.toList obsolete - in DG.filter (`S.member` allObsolete) graph diff --git a/src/Hakyll/Core/Rules.hs b/src/Hakyll/Core/Rules.hs index 28ae555..ae476b7 100644 --- a/src/Hakyll/Core/Rules.hs +++ b/src/Hakyll/Core/Rules.hs @@ -117,6 +117,7 @@ addCompilers :: (Binary a, Typeable a, Writable a) -> Rules -- ^ Resulting rules addCompilers identifier compiler = RulesM $ tell $ RuleSet mempty $ - [(identifier, compiler >>^ makeRule)] + [(identifier, compiler >>> arr makeRule )] where - makeRule = MetaCompileRule . map (second (>>^ CompileRule . compiledItem)) + makeRule = MetaCompileRule . map (second box) + box = (>>> fromDependency identifier >>^ CompileRule . compiledItem) diff --git a/src/Hakyll/Core/Run.hs b/src/Hakyll/Core/Run.hs index dea848b..324294f 100644 --- a/src/Hakyll/Core/Run.hs +++ b/src/Hakyll/Core/Run.hs @@ -3,6 +3,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Hakyll.Core.Run where +import Prelude hiding (reverse) import Control.Applicative import Control.Monad.Reader import Control.Monad.State @@ -30,7 +31,6 @@ import Hakyll.Core.Rules import Hakyll.Core.DirectedGraph import Hakyll.Core.DirectedGraph.Dot import Hakyll.Core.DirectedGraph.DependencySolver -import Hakyll.Core.DirectedGraph.ObsoleteFilter import Hakyll.Core.Writable import Hakyll.Core.Store import Hakyll.Core.CompiledItem @@ -49,6 +49,7 @@ hakyll rules = do , hakyllResourceProvider = provider , hakyllStore = store , hakyllModified = S.empty + , hakyllObsolete = S.empty } data HakyllEnvironment = HakyllEnvironment @@ -56,6 +57,7 @@ data HakyllEnvironment = HakyllEnvironment , hakyllResourceProvider :: ResourceProvider , hakyllStore :: Store , hakyllModified :: Set Identifier + , hakyllObsolete :: Set Identifier } newtype Hakyll a = Hakyll @@ -98,19 +100,22 @@ addNewCompilers oldCompilers newCompilers = Hakyll $ do -- Create the dependency graph graph = fromList dependencies + liftIO $ writeDot "dependencies.dot" show graph + -- Check which items are up-to-date. This only needs to happen for the new -- compilers oldModified <- hakyllModified <$> ask newModified <- liftIO $ modified provider store $ map fst newCompilers - let modified' = oldModified `S.union` newModified + oldObsolete <- hakyllObsolete <$> ask - liftIO $ putStrLn $ show modified' - - let -- Try to reduce the graph using this modified information - reducedGraph = filterObsolete modified' graph + let modified' = oldModified `S.union` newModified + + -- Find obsolete items + obsolete = reachableNodes (oldObsolete `S.union` modified') $ + reverse graph - let -- Solve the graph - ordered = solveDependencies reducedGraph + -- Solve the graph, retain only the obsolete items + ordered = filter (`S.member` obsolete) $ solveDependencies graph -- Join the order with the compilers again orderedCompilers = map (id &&& (compilerMap M.!)) ordered @@ -118,11 +123,13 @@ addNewCompilers oldCompilers newCompilers = Hakyll $ do liftIO $ putStrLn "Adding compilers..." -- Now run the ordered list of compilers - local (updateModified modified') $ unHakyll $ runCompilers orderedCompilers + local (updateEnv modified' obsolete) $ + unHakyll $ runCompilers orderedCompilers where -- Add the modified information for the new compilers - updateModified modified' env = env + updateEnv modified' obsolete env = env { hakyllModified = modified' + , hakyllObsolete = obsolete } runCompilers :: [(Identifier, Compiler () CompileRule)] -- cgit v1.2.3 From df8e221aef147ded6e8fe7331619913cc2f51513 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Sat, 8 Jan 2011 09:09:11 +0100 Subject: Fully qualified errors --- src/Hakyll/Core/CompiledItem.hs | 2 +- src/Hakyll/Core/DirectedGraph/DependencySolver.hs | 5 ++++- src/Hakyll/Core/DirectedGraph/Internal.hs | 5 ++++- src/Hakyll/Web/Pandoc.hs | 2 +- src/Hakyll/Web/Template/Internal.hs | 3 ++- 5 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src/Hakyll/Core/DirectedGraph') diff --git a/src/Hakyll/Core/CompiledItem.hs b/src/Hakyll/Core/CompiledItem.hs index d12d172..a803971 100644 --- a/src/Hakyll/Core/CompiledItem.hs +++ b/src/Hakyll/Core/CompiledItem.hs @@ -36,4 +36,4 @@ unCompiledItem :: (Binary a, Typeable a, Writable a) -> a unCompiledItem (CompiledItem x) = case cast x of Just x' -> x' - Nothing -> error "unCompiledItem: Unsupported type" + Nothing -> error "Hakyll.Core.CompiledItem.unCompiledItem: Unsupported type" diff --git a/src/Hakyll/Core/DirectedGraph/DependencySolver.hs b/src/Hakyll/Core/DirectedGraph/DependencySolver.hs index 17a4b69..214211b 100644 --- a/src/Hakyll/Core/DirectedGraph/DependencySolver.hs +++ b/src/Hakyll/Core/DirectedGraph/DependencySolver.hs @@ -60,8 +60,11 @@ order temp stack set graph@(DirectedGraph graph') -- one first... (dep : _) -> if (nodeTag dep) `S.member` set -- The dependency is already in our stack - cycle detected! - then error "order: Cycle detected!" -- TODO: Dump cycle + then cycleError -- Continue with the dependency else order temp (dep : node : stackTail) (S.insert (nodeTag dep) set) graph + where + cycleError = error $ "Hakyll.Core.DirectedGraph.DependencySolver.order: " + ++ "Cycle detected!" -- TODO: Dump cycle diff --git a/src/Hakyll/Core/DirectedGraph/Internal.hs b/src/Hakyll/Core/DirectedGraph/Internal.hs index 52a712d..bc9cd92 100644 --- a/src/Hakyll/Core/DirectedGraph/Internal.hs +++ b/src/Hakyll/Core/DirectedGraph/Internal.hs @@ -24,8 +24,11 @@ data Node a = Node -- appendNodes :: Ord a => Node a -> Node a -> Node a appendNodes (Node t1 n1) (Node t2 n2) - | t1 /= t2 = error "appendNodes: Appending differently tagged nodes" + | t1 /= t2 = error' | otherwise = Node t1 (n1 `S.union` n2) + where + error' = error $ "Hakyll.Core.DirectedGraph.Internal.appendNodes: " + ++ "Appending differently tagged nodes" -- | Type used to represent a directed graph -- diff --git a/src/Hakyll/Web/Pandoc.hs b/src/Hakyll/Web/Pandoc.hs index 7fecdc4..2656212 100644 --- a/src/Hakyll/Web/Pandoc.hs +++ b/src/Hakyll/Web/Pandoc.hs @@ -50,7 +50,7 @@ readPandocWith state fileType' = case fileType' of Markdown -> P.readMarkdown state Rst -> P.readRST state t -> error $ - "readPandoc: I don't know how to read " ++ show t + "Hakyll.Web.readPandocWith: I don't know how to read " ++ show t -- | Write a document (as HTML) using pandoc, with the default options -- diff --git a/src/Hakyll/Web/Template/Internal.hs b/src/Hakyll/Web/Template/Internal.hs index be10881..096c928 100644 --- a/src/Hakyll/Web/Template/Internal.hs +++ b/src/Hakyll/Web/Template/Internal.hs @@ -41,4 +41,5 @@ instance Binary TemplateElement where 0 -> Chunk <$> get 1 -> Identifier <$> get 2 -> Escaped <$> get - _ -> error "Error reading cached template" + _ -> error $ "Hakyll.Web.Template.Internal: " + ++ "Error reading cached template" -- cgit v1.2.3 From 6e7dc0e58fd2d7814934e0c041a4e18232102087 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Fri, 14 Jan 2011 08:50:34 +0100 Subject: Micro-cleanup --- src/Hakyll/Core/CompiledItem.hs | 7 ++++--- src/Hakyll/Core/Compiler/Internal.hs | 3 +-- src/Hakyll/Core/DirectedGraph.hs | 4 ++-- src/Hakyll/Core/DirectedGraph/DependencySolver.hs | 6 +++--- src/Hakyll/Core/DirectedGraph/Internal.hs | 4 ++-- src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs | 2 +- src/Hakyll/Core/Route.hs | 4 ++-- src/Hakyll/Core/Rules.hs | 2 +- src/Hakyll/Core/Run.hs | 5 ++--- src/Hakyll/Web/Pandoc.hs | 2 +- 10 files changed, 19 insertions(+), 20 deletions(-) (limited to 'src/Hakyll/Core/DirectedGraph') diff --git a/src/Hakyll/Core/CompiledItem.hs b/src/Hakyll/Core/CompiledItem.hs index a803971..fe6730b 100644 --- a/src/Hakyll/Core/CompiledItem.hs +++ b/src/Hakyll/Core/CompiledItem.hs @@ -11,6 +11,7 @@ module Hakyll.Core.CompiledItem import Data.Binary (Binary) import Data.Typeable (Typeable, cast) +import Data.Maybe (fromMaybe) import Hakyll.Core.Writable @@ -34,6 +35,6 @@ compiledItem = CompiledItem unCompiledItem :: (Binary a, Typeable a, Writable a) => CompiledItem -> a -unCompiledItem (CompiledItem x) = case cast x of - Just x' -> x' - Nothing -> error "Hakyll.Core.CompiledItem.unCompiledItem: Unsupported type" +unCompiledItem (CompiledItem x) = fromMaybe error' $ cast x + where + error' = error "Hakyll.Core.CompiledItem.unCompiledItem: Unsupported type" diff --git a/src/Hakyll/Core/Compiler/Internal.hs b/src/Hakyll/Core/Compiler/Internal.hs index 938d81a..5ae2f5b 100644 --- a/src/Hakyll/Core/Compiler/Internal.hs +++ b/src/Hakyll/Core/Compiler/Internal.hs @@ -92,8 +92,7 @@ runCompilerJob compiler identifier provider route store modified = runCompilerDependencies :: Compiler () a -> ResourceProvider -> Dependencies -runCompilerDependencies compiler provider = - runReader (compilerDependencies compiler) provider +runCompilerDependencies compiler = runReader (compilerDependencies compiler) fromJob :: (a -> CompilerM b) -> Compiler a b diff --git a/src/Hakyll/Core/DirectedGraph.hs b/src/Hakyll/Core/DirectedGraph.hs index 66905f7..a81868e 100644 --- a/src/Hakyll/Core/DirectedGraph.hs +++ b/src/Hakyll/Core/DirectedGraph.hs @@ -65,12 +65,12 @@ reachableNodes set graph = reachable (setNeighbours set) set sanitize' = S.filter (`S.notMember` visited) neighbours' = setNeighbours (sanitize' next) - setNeighbours = S.unions . map (flip neighbours graph) . S.toList + setNeighbours = S.unions . map (`neighbours` graph) . S.toList -- | Remove all dangling pointers, i.e. references to notes that do -- not actually exist in the graph. -- sanitize :: Ord a => DirectedGraph a -> DirectedGraph a -sanitize (DirectedGraph graph) = DirectedGraph $ M.map sanitize' $ graph +sanitize (DirectedGraph graph) = DirectedGraph $ M.map sanitize' graph where sanitize' (Node t n) = Node t $ S.filter (`M.member` graph) n diff --git a/src/Hakyll/Core/DirectedGraph/DependencySolver.hs b/src/Hakyll/Core/DirectedGraph/DependencySolver.hs index 214211b..54826ff 100644 --- a/src/Hakyll/Core/DirectedGraph/DependencySolver.hs +++ b/src/Hakyll/Core/DirectedGraph/DependencySolver.hs @@ -10,7 +10,7 @@ module Hakyll.Core.DirectedGraph.DependencySolver import Prelude import qualified Prelude as P import Data.Set (Set) -import Data.Maybe (catMaybes) +import Data.Maybe (mapMaybe) import qualified Data.Map as M import qualified Data.Set as S @@ -48,7 +48,7 @@ order temp stack set graph@(DirectedGraph graph') -- Check which dependencies are still in the graph let tag = nodeTag node deps = S.toList $ nodeNeighbours node - unsatisfied = catMaybes $ map (flip M.lookup graph') deps + unsatisfied = mapMaybe (`M.lookup` graph') deps in case unsatisfied of -- All dependencies for node are satisfied, we can return it and @@ -58,7 +58,7 @@ order temp stack set graph@(DirectedGraph graph') -- There is at least one dependency left. We need to solve that -- one first... - (dep : _) -> if (nodeTag dep) `S.member` set + (dep : _) -> if nodeTag dep `S.member` set -- The dependency is already in our stack - cycle detected! then cycleError -- Continue with the dependency diff --git a/src/Hakyll/Core/DirectedGraph/Internal.hs b/src/Hakyll/Core/DirectedGraph/Internal.hs index bc9cd92..5b02ad6 100644 --- a/src/Hakyll/Core/DirectedGraph/Internal.hs +++ b/src/Hakyll/Core/DirectedGraph/Internal.hs @@ -16,8 +16,8 @@ import qualified Data.Set as S -- | A node in the directed graph -- data Node a = Node - { nodeTag :: a -- ^ Tag identifying the node - , nodeNeighbours :: (Set a) -- ^ Edges starting at this node + { nodeTag :: a -- ^ Tag identifying the node + , nodeNeighbours :: Set a -- ^ Edges starting at this node } deriving (Show) -- | Append two nodes. Useful for joining graphs. diff --git a/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs b/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs index 72d38be..a2376c2 100644 --- a/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs +++ b/src/Hakyll/Core/ResourceProvider/FileResourceProvider.hs @@ -17,7 +17,7 @@ import Hakyll.Core.Util.File fileResourceProvider :: IO ResourceProvider fileResourceProvider = do list <- map parseIdentifier <$> getRecursiveContents "." - return $ ResourceProvider + return ResourceProvider { resourceList = list , resourceString = readFile . toFilePath , resourceLazyByteString = LB.readFile . toFilePath diff --git a/src/Hakyll/Core/Route.hs b/src/Hakyll/Core/Route.hs index 195768c..f3f0b7f 100644 --- a/src/Hakyll/Core/Route.hs +++ b/src/Hakyll/Core/Route.hs @@ -59,8 +59,8 @@ idRoute = Route $ Just . toFilePath -- > Just "posts/the-art-of-trolling.html" -- setExtension :: String -> Route -setExtension exension = Route $ fmap (flip replaceExtension exension) - . unRoute idRoute +setExtension extension = Route $ fmap (`replaceExtension` extension) + . unRoute idRoute -- | Modify a route: apply the route if the identifier matches the given -- pattern, fail otherwise. diff --git a/src/Hakyll/Core/Rules.hs b/src/Hakyll/Core/Rules.hs index ae476b7..dd0d9a6 100644 --- a/src/Hakyll/Core/Rules.hs +++ b/src/Hakyll/Core/Rules.hs @@ -116,7 +116,7 @@ addCompilers :: (Binary a, Typeable a, Writable a) -- ^ Compiler generating the other compilers -> Rules -- ^ Resulting rules -addCompilers identifier compiler = RulesM $ tell $ RuleSet mempty $ +addCompilers identifier compiler = RulesM $ tell $ RuleSet mempty [(identifier, compiler >>> arr makeRule )] where makeRule = MetaCompileRule . map (second box) diff --git a/src/Hakyll/Core/Run.hs b/src/Hakyll/Core/Run.hs index 77b3fab..c81a5ff 100644 --- a/src/Hakyll/Core/Run.hs +++ b/src/Hakyll/Core/Run.hs @@ -16,7 +16,6 @@ import Data.Monoid (mempty, mappend) import Data.Typeable (Typeable) import Data.Binary (Binary) import System.FilePath (()) -import Control.Applicative ((<$>)) import Data.Set (Set) import qualified Data.Set as S @@ -115,7 +114,7 @@ addNewCompilers oldCompilers newCompilers = Hakyll $ do -- Find the old graph and append the new graph to it. This forms the -- complete graph - completeGraph <- (mappend currentGraph) . hakyllGraph <$> get + completeGraph <- mappend currentGraph . hakyllGraph <$> get liftIO $ writeDot "dependencies.dot" show completeGraph @@ -190,6 +189,6 @@ runCompilers ((id', compiler) : compilers) = Hakyll $ do unHakyll $ runCompilers compilers -- Metacompiler, slightly more complicated - MetaCompileRule newCompilers -> do + MetaCompileRule newCompilers -> -- Actually I was just kidding, it's not hard at all unHakyll $ addNewCompilers compilers newCompilers diff --git a/src/Hakyll/Web/Pandoc.hs b/src/Hakyll/Web/Pandoc.hs index 2656212..acd5f56 100644 --- a/src/Hakyll/Web/Pandoc.hs +++ b/src/Hakyll/Web/Pandoc.hs @@ -89,7 +89,7 @@ pageRenderPandocWith :: P.ParserState -> P.WriterOptions -> Compiler (Page String) (Page String) pageRenderPandocWith state options = - pageReadPandocWith state >>^ (fmap $ writePandocWith options) + pageReadPandocWith state >>^ fmap (writePandocWith options) -- | The default reader options for pandoc parsing in hakyll -- -- cgit v1.2.3