diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## Stache 1.2.0
+
+* Added `compileMustacheDir'` and `getMusthacheFilesInDir'` that allow for a
+  custom template predicate. Also exposed `isMustacheFile` as the default
+  predicate used by functions like `compileMustacheDir`.
+
+* Abandon attempts to support GHC 7.8.
+
 ## Stache 1.1.2
 
 * Fixed compilation of the test suite with Cabal 2.0/GHC 8.2.1.
diff --git a/Text/Mustache.hs b/Text/Mustache.hs
--- a/Text/Mustache.hs
+++ b/Text/Mustache.hs
@@ -82,6 +82,7 @@
   , displayMustacheWarning
     -- * Compiling
   , compileMustacheDir
+  , compileMustacheDir'
   , compileMustacheFile
   , compileMustacheText
     -- * Rendering
diff --git a/Text/Mustache/Compile.hs b/Text/Mustache/Compile.hs
--- a/Text/Mustache/Compile.hs
+++ b/Text/Mustache/Compile.hs
@@ -15,7 +15,10 @@
 
 module Text.Mustache.Compile
   ( compileMustacheDir
+  , compileMustacheDir'
   , getMustacheFilesInDir
+  , getMustacheFilesInDir'
+  , isMustacheFile
   , compileMustacheFile
   , compileMustacheText )
 where
@@ -33,24 +36,34 @@
 import qualified Data.Text.IO    as T
 import qualified System.FilePath as F
 
-#if !MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
-
 -- | Compile all templates in specified directory and select one. Template
 -- files should have the extension @mustache@, (e.g. @foo.mustache@) to be
 -- recognized. This function /does not/ scan the directory recursively.
 --
 -- The action can throw the same exceptions as 'getDirectoryContents', and
 -- 'T.readFile'.
+--
+-- > compileMustacheDir = complieMustacheDir' isMustacheFile
 
 compileMustacheDir :: MonadIO m
   => PName             -- ^ Which template to select after compiling
   -> FilePath          -- ^ Directory with templates
   -> m Template        -- ^ The resulting template
-compileMustacheDir pname path =
-  getMustacheFilesInDir path >>=
-  liftM selectKey . foldM f (Template undefined M.empty)
+compileMustacheDir = compileMustacheDir' isMustacheFile
+
+-- | The same as 'compileMustacheDir', but allows using a custom predicate
+-- for template selection.
+--
+-- @since 1.2.0
+
+compileMustacheDir' :: MonadIO m
+  => (FilePath -> Bool) -- ^ Template selection predicate
+  -> PName             -- ^ Which template to select after compiling
+  -> FilePath          -- ^ Directory with templates
+  -> m Template        -- ^ The resulting template
+compileMustacheDir' predicate pname path =
+  getMustacheFilesInDir' predicate path >>=
+  fmap selectKey . foldM f (Template undefined M.empty)
   where
     selectKey t = t { templateActual = pname }
     f (Template _ old) fp = do
@@ -65,11 +78,31 @@
 getMustacheFilesInDir :: MonadIO m
   => FilePath          -- ^ Directory with templates
   -> m [FilePath]
-getMustacheFilesInDir path = liftIO $
+getMustacheFilesInDir = getMustacheFilesInDir' isMustacheFile
+
+-- | Return a list of templates found via a predicate in given directory.
+-- The returned paths are absolute.
+--
+-- @since 1.2.0
+
+getMustacheFilesInDir' :: MonadIO m
+  => (FilePath -> Bool) -- ^ Mustache file selection predicate
+  -> FilePath          -- ^ Directory with templates
+  -> m [FilePath]
+getMustacheFilesInDir' predicate path = liftIO $
   getDirectoryContents path >>=
-  filterM isMustacheFile . fmap (F.combine path) >>=
+  filterM f . fmap (F.combine path) >>=
   mapM makeAbsolute
+  where
+    f p = (&& predicate p) <$> doesFileExist p
 
+-- | The default Mustache file predicate.
+--
+-- @since 1.2.0
+
+isMustacheFile :: FilePath -> Bool
+isMustacheFile path = F.takeExtension path == ".mustache"
+
 -- | Compile a single Mustache template and select it.
 --
 -- The action can throw the same exceptions as 'T.readFile'.
@@ -96,14 +129,6 @@
 
 ----------------------------------------------------------------------------
 -- Helpers
-
--- | Check if a given 'FilePath' points to a mustache file.
-
-isMustacheFile :: FilePath -> IO Bool
-isMustacheFile path = do
-  exists <- doesFileExist path
-  let rightExtension = F.takeExtension path == ".mustache"
-  return (exists && rightExtension)
 
 -- | Build a 'PName' from given 'FilePath'.
 
diff --git a/Text/Mustache/Compile/TH.hs b/Text/Mustache/Compile/TH.hs
--- a/Text/Mustache/Compile/TH.hs
+++ b/Text/Mustache/Compile/TH.hs
@@ -21,6 +21,7 @@
 
 module Text.Mustache.Compile.TH
   ( compileMustacheDir
+  , compileMustacheDir'
   , compileMustacheFile
   , compileMustacheText
   , mustache )
@@ -37,10 +38,6 @@
 import qualified Data.Text             as T
 import qualified Text.Mustache.Compile as C
 
-#if !MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
-
 #if MIN_VERSION_template_haskell(2,11,0)
 import Language.Haskell.TH.Syntax (dataToExpQ)
 #else
@@ -54,13 +51,29 @@
 -- recognized. This function /does not/ scan the directory recursively.
 --
 -- This version compiles the templates at compile time.
+--
+-- > compileMustacheDir = compileMustacheDir' isMustacheFile
 
 compileMustacheDir
   :: PName             -- ^ Which template to select after compiling
   -> FilePath          -- ^ Directory with templates
   -> Q Exp             -- ^ The resulting template
-compileMustacheDir pname path = do
-  runIO (C.getMustacheFilesInDir path) >>= mapM_ addDependentFile
+compileMustacheDir = compileMustacheDir' C.isMustacheFile
+
+-- | The same as 'compileMustacheDir', but allows using a custom predicate
+-- for template selection.
+--
+-- This version compiles the templates at compile time.
+--
+-- @since 1.2.0
+
+compileMustacheDir'
+  :: (FilePath -> Bool) -- ^ Template selection predicate
+  -> PName             -- ^ Which template to select after compiling
+  -> FilePath          -- ^ Directory with templates
+  -> Q Exp             -- ^ The resulting template
+compileMustacheDir' predicate pname path = do
+  runIO (C.getMustacheFilesInDir' predicate path) >>= mapM_ addDependentFile
   (runIO . try) (C.compileMustacheDir pname path) >>= handleEither
 
 -- | Compile single Mustache template and select it.
diff --git a/Text/Mustache/Render.hs b/Text/Mustache/Render.hs
--- a/Text/Mustache/Render.hs
+++ b/Text/Mustache/Render.hs
@@ -39,10 +39,6 @@
 import qualified Data.Text.Lazy.Encoding as TL
 import qualified Data.Vector             as V
 
-#if !MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
-
 ----------------------------------------------------------------------------
 -- The rendering monad
 
diff --git a/stache.cabal b/stache.cabal
--- a/stache.cabal
+++ b/stache.cabal
@@ -1,7 +1,7 @@
 name:                 stache
-version:              1.1.2
+version:              1.2.0
 cabal-version:        >= 1.18
-tested-with:          GHC==7.8.4, GHC==7.10.3, GHC==8.0.2, GHC==8.2.1
+tested-with:          GHC==7.10.3, GHC==8.0.2, GHC==8.2.1
 license:              BSD3
 license-file:         LICENSE.md
 author:               Mark Karpov <markkarpov92@gmail.com>
@@ -29,7 +29,7 @@
 
 library
   build-depends:      aeson            >= 0.11 && < 1.3
-                    , base             >= 4.7  && < 5.0
+                    , base             >= 4.8  && < 5.0
                     , bytestring       >= 0.10 && < 0.11
                     , containers       >= 0.5  && < 0.6
                     , deepseq          >= 1.4  && < 1.5
@@ -52,7 +52,7 @@
                     , Text.Mustache.Render
                     , Text.Mustache.Type
   if flag(dev)
-    ghc-options:      -Wall -Werror -fsimpl-tick-factor=150
+    ghc-options:      -O0 -Wall -Werror -fsimpl-tick-factor=150
   else
     ghc-options:      -O2 -Wall -fsimpl-tick-factor=150
   default-language:   Haskell2010
@@ -62,7 +62,7 @@
   hs-source-dirs:     tests
   type:               exitcode-stdio-1.0
   build-depends:      aeson            >= 0.11 && < 1.3
-                    , base             >= 4.7  && < 5.0
+                    , base             >= 4.8  && < 5.0
                     , containers       >= 0.5  && < 0.6
                     , hspec            >= 2.0  && < 3.0
                     , hspec-megaparsec >= 1.0  && < 2.0
@@ -77,7 +77,7 @@
   if !impl(ghc >= 8.0)
     build-depends:    semigroups     == 0.18.*
   if flag(dev)
-    ghc-options:      -Wall -Werror
+    ghc-options:      -O0 -Wall -Werror
   else
     ghc-options:      -O2 -Wall
   default-language:   Haskell2010
@@ -87,7 +87,7 @@
   hs-source-dirs:     mustache-spec
   type:               exitcode-stdio-1.0
   build-depends:      aeson            >= 0.11 && < 1.3
-                    , base             >= 4.7  && < 5.0
+                    , base             >= 4.8  && < 5.0
                     , bytestring       >= 0.10 && < 0.11
                     , containers       >= 0.5  && < 0.6
                     , file-embed
@@ -107,7 +107,7 @@
   hs-source-dirs:     bench
   type:               exitcode-stdio-1.0
   build-depends:      aeson            >= 0.11 && < 1.3
-                    , base             >= 4.7  && < 5.0
+                    , base             >= 4.8  && < 5.0
                     , criterion        >= 0.6.2.1 && < 1.3
                     , deepseq          >= 1.4  && < 1.5
                     , megaparsec       >= 6.0  && < 7.0
diff --git a/tests/Text/Mustache/ParserSpec.hs b/tests/Text/Mustache/ParserSpec.hs
--- a/tests/Text/Mustache/ParserSpec.hs
+++ b/tests/Text/Mustache/ParserSpec.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP               #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Text.Mustache.ParserSpec
@@ -12,10 +11,6 @@
 import Text.Megaparsec
 import Text.Mustache.Parser
 import Text.Mustache.Type
-
-#if !MIN_VERSION_base(4,8,0)
-import Control.Applicative (pure)
-#endif
 
 main :: IO ()
 main = hspec spec
diff --git a/tests/Text/Mustache/RenderSpec.hs b/tests/Text/Mustache/RenderSpec.hs
--- a/tests/Text/Mustache/RenderSpec.hs
+++ b/tests/Text/Mustache/RenderSpec.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP               #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Text.Mustache.RenderSpec
@@ -13,10 +12,6 @@
 import Text.Mustache.Render
 import Text.Mustache.Type
 import qualified Data.Map as M
-
-#if !MIN_VERSION_base(4,8,0)
-import Control.Applicative (pure)
-#endif
 
 main :: IO ()
 main = hspec spec
