diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,19 @@
 
 # Changelog by versions
 
+## From 3.21.0.0 to 3.22.0.0
+* More liftLX, commX and envX functions. (KommuSoft)
+* New module: Text.LaTeX.Packages.Acronym. (KommuSoft)
+* Expanded BibLaTeX module with new functionality. (leftaroundabout)
+* Dropped support for GHC-7.8 (and earlier version).
+
+## From 3.20.0.1 to 3.21.0.0
+
+* Replace wl-pprint-extras with prettyprinter in the latex pretty-printer.
+* Now 'table' takes a list of positions. (breaking change)
+* Added constructors Here and ForcePos to the Pos type.
+* Make argument of 'nopagebreak' optional.
+
 ## From 3.18.0.0 to 3.19.0.0
 
 * Fix build with GHC 8.4.1 (#113) (leftaroundabout).
diff --git a/Examples/biblatexDOI.hs b/Examples/biblatexDOI.hs
new file mode 100644
--- /dev/null
+++ b/Examples/biblatexDOI.hs
@@ -0,0 +1,24 @@
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PackageImports #-}
+
+import Text.LaTeX
+import Text.LaTeX.Packages.BibLaTeX
+import Text.LaTeX.Packages.Inputenc
+import System.IO (writeFile)
+import System.Process (callProcess)
+
+main :: IO ()
+main = do
+  execLaTeXT bibLaTeXExample >>= renderFile "biblatexDOI.tex"
+  mapM_ (`callProcess`["biblatexDOI"]) ["pdflatex", "biber", "pdflatex"]
+
+bibLaTeXExample :: LaTeXT IO ()
+bibLaTeXExample = do
+   documentclass [] article
+   usepackage ["backend=biber"] biblatex
+   documentWithDOIReferences
+        (masterBibFile "/home/data/promotion/Literatur/literatur.bib") $ do
+     "We can cite documents by simply giving a DOI, such as "
+     citeDOI "123456789" "J Doe et al 1950: Investigation of Foo"
+     printbibliography
diff --git a/Examples/matrices.hs b/Examples/matrices.hs
--- a/Examples/matrices.hs
+++ b/Examples/matrices.hs
@@ -19,4 +19,4 @@
  usepackage [] amsmath
 
 theBody :: Monad m => LaTeXT_ m
-theBody = equation_ $ pmatrix Nothing $ (identity 5 :: Matrix Int)
+theBody = equation_ $ pmatrix Nothing (identity 5 :: Matrix Int)
diff --git a/Examples/multirow.hs b/Examples/multirow.hs
--- a/Examples/multirow.hs
+++ b/Examples/multirow.hs
@@ -15,8 +15,7 @@
   document exampleBody
 
 minitab :: Monad m => TableSpec -> LaTeXT_ m -> LaTeXT_ m
-minitab tableSpec text =
-  tabular Nothing [tableSpec] text
+minitab tableSpec = tabular Nothing [tableSpec]
 
 exampleBody :: Monad m => LaTeXT_ m
 exampleBody = do
diff --git a/HaTeX.cabal b/HaTeX.cabal
--- a/HaTeX.cabal
+++ b/HaTeX.cabal
@@ -1,5 +1,5 @@
 Name: HaTeX
-Version: 3.21.0.0
+Version: 3.22.0.0
 Author: Daniel Díaz
 Category: LaTeX
 Build-type: Simple
@@ -65,6 +65,7 @@
                , transformers >= 0.2.2 && < 0.6
                , containers >= 0.4.2.1 && < 0.7
                , hashable >= 1.2 && < 1.4
+               , bibtex >= 0.1 && < 0.2
                , matrix
                  -- Testing
                , QuickCheck
@@ -92,6 +93,7 @@
         Text.LaTeX.Base.Writer
         Text.LaTeX.Base.Warnings
         -- Packages
+        Text.LaTeX.Packages.Acronym
         Text.LaTeX.Packages.AMSFonts
         Text.LaTeX.Packages.AMSMath
         Text.LaTeX.Packages.AMSSymb
diff --git a/Text/LaTeX/Base.hs b/Text/LaTeX/Base.hs
--- a/Text/LaTeX/Base.hs
+++ b/Text/LaTeX/Base.hs
@@ -27,7 +27,7 @@
  ( -- * @LaTeX@ datatype
    LaTeX
    -- * Escaping reserved characters
- , protectString , protectText
+ , protectString, protectText
    -- * Internal re-exports
  , module Text.LaTeX.Base.Render
  , module Text.LaTeX.Base.Types
@@ -45,9 +45,6 @@
 -- Internal modules
 import Text.LaTeX.Base.Syntax
   ( LaTeX
-#if __GLASGOW_HASKELL__ < 704
-  , (<>)
-#endif
   , protectString
   , protectText)
 import Text.LaTeX.Base.Render
diff --git a/Text/LaTeX/Base/Class.hs b/Text/LaTeX/Base/Class.hs
--- a/Text/LaTeX/Base/Class.hs
+++ b/Text/LaTeX/Base/Class.hs
@@ -16,17 +16,14 @@
    --
    -- > liftLN f x1 ... xN = liftListL (\[x1,...,xN] -> f x1 ... xN) [x1,...,xN]
    --
- , liftL
- , liftL2
- , liftL3
+ , liftL, liftL2, liftL3, liftL4, liftL5, liftL6, liftL7, liftL8, liftL9
    -- ** Others
- , comm0
- , comm1
- , comm2
- , comm3
+ , comm0, comm1, comm2, comm3, comm4, comm5, comm6, comm7, comm8, comm9
  , commS
- , braces
- , squareBraces
+ , fixComm, optFixComm
+ , env0, env1, env2, env3, env4, env5, env6, env7, env8, env9
+ , fixEnv
+ , braces, squareBraces
  , raw
  ) where
 
@@ -40,33 +37,86 @@
 -- | This is the class of 'LaTeX' code generators. It has 'Monoid' and 'IsString' as
 --   superclasses.
 class (Monoid l,IsString l) => LaTeXC l where
- -- | This method must take a function that combines a list of 'LaTeX' values into a new one,
- --   and creates a function that combines @l@-typed values. The combining function can be
- --   seen as a function with 0 or more 'LaTeX' arguments with a 'LaTeX' value as output.
- liftListL :: ([LaTeX] -> LaTeX) -> [l] -> l
+    -- | This method must take a function that combines a list of 'LaTeX' values into a new one,
+    --   and creates a function that combines @l@-typed values. The combining function can be
+    --   seen as a function with 0 or more 'LaTeX' arguments with a 'LaTeX' value as output.
+    liftListL :: ([LaTeX] -> LaTeX) -> [l] -> l
 
 -- | This instance just sets @liftListL = id@.
 instance LaTeXC LaTeX where
- liftListL = id
+    liftListL = id
 
 -- COMBINATORS
 
 -- | Map a 'LaTeX' value to its equivalent in any 'LaTeXC' instance.
 fromLaTeX :: LaTeXC l => LaTeX -> l
-fromLaTeX l = liftListL (\_ -> l) []
+fromLaTeX l = liftListL (const l) []
 
 -- | Lift a inner function of 'LaTeX' values into any 'LaTeXC' instance.
 liftL :: LaTeXC l => (LaTeX -> LaTeX) -> l -> l
-liftL f x = liftListL (\[x] -> f x) [x]
+liftL f x1 = liftListL (\[x1] -> f x1) [x1]
 
 -- | Variant of 'liftL' with a two arguments function.
 liftL2 :: LaTeXC l => (LaTeX -> LaTeX -> LaTeX) -> l -> l -> l
-liftL2 f x y = liftListL (\[x,y] -> f x y) [x,y]
+liftL2 f x1 x2 = liftListL (\[x1,x2] -> f x1 x2) [x1,x2]
 
 -- | Variant of 'liftL' with a three arguments function.
 liftL3 :: LaTeXC l => (LaTeX -> LaTeX -> LaTeX -> LaTeX) -> l -> l -> l -> l
-liftL3 f x y z = liftListL (\[x,y,z] -> f x y z) [x,y,z]
+liftL3 f x1 x2 x3 = liftListL (\[x1,x2,x3] -> f x1 x2 x3) [x1,x2,x3]
 
+-- | Variant of 'liftL' with a four arguments function.
+liftL4 :: LaTeXC l => (LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX) -> l -> l -> l -> l -> l
+liftL4 f x1 x2 x3 x4 = liftListL (\[x1,x2,x3,x4] -> f x1 x2 x3 x4) [x1,x2,x3,x4]
+
+-- | Variant of 'liftL' with a five arguments function.
+liftL5 :: LaTeXC l => (LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX) -> l -> l -> l -> l -> l -> l
+liftL5 f x1 x2 x3 x4 x5 = liftListL (\[x1,x2,x3,x4,x5] -> f x1 x2 x3 x4 x5) [x1,x2,x3,x4,x5]
+
+-- | Variant of 'liftL' with a six arguments function.
+liftL6 :: LaTeXC l => (LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX) -> l -> l -> l -> l -> l -> l -> l
+liftL6 f x1 x2 x3 x4 x5 x6 = liftListL (\[x1,x2,x3,x4,x5,x6] -> f x1 x2 x3 x4 x5 x6) [x1,x2,x3,x4,x5,x6]
+
+-- | Variant of 'liftL' with a seven arguments function.
+liftL7 :: LaTeXC l => (LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX) -> l -> l -> l -> l -> l -> l -> l -> l
+liftL7 f x1 x2 x3 x4 x5 x6 x7 = liftListL (\[x1,x2,x3,x4,x5,x6,x7] -> f x1 x2 x3 x4 x5 x6 x7) [x1,x2,x3,x4,x5,x6,x7]
+
+-- | Variant of 'liftL' with an eight arguments function.
+liftL8 :: LaTeXC l => (LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX) -> l -> l -> l -> l -> l -> l -> l -> l -> l
+liftL8 f x1 x2 x3 x4 x5 x6 x7 x8 = liftListL (\[x1,x2,x3,x4,x5,x6,x7,x8] -> f x1 x2 x3 x4 x5 x6 x7 x8) [x1,x2,x3,x4,x5,x6,x7,x8]
+
+-- | Variant of 'liftL' with a nine arguments function.
+liftL9 :: LaTeXC l => (LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX -> LaTeX) -> l -> l -> l -> l -> l -> l -> l -> l -> l -> l
+liftL9 f x1 x2 x3 x4 x5 x6 x7 x8 x9 = liftListL (\[x1,x2,x3,x4,x5,x6,x7,x8,x9] -> f x1 x2 x3 x4 x5 x6 x7 x8 x9) [x1,x2,x3,x4,x5,x6,x7,x8,x9]
+
+
+-- | Map the given functor of LaTeX values to fixed TeX arguments.
+fixArgs :: Functor f => f LaTeX -> f TeXArg
+fixArgs = fmap FixArg
+
+-- | Map the first 'n' elements as optional arguments, and the remaining ones as
+-- fixed arguments. Most LaTeX commands are structured with first a sequence of
+-- optional arguments, followed by a sequence of fixed arguments.
+optFixArgs :: Int -> [LaTeX] -> [TeXArg]
+optFixArgs _ [] = []
+optFixArgs k xa@(x:xs) | k <= 0 = map FixArg xa
+                       | otherwise = OptArg x : optFixArgs (k-1) xs
+
+-- | Call a LaTeX command where all the arguments in the list are fixed
+-- arguments.
+fixComm :: LaTeXC l => String -> [l] -> l
+fixComm str = liftListL (TeXComm str . fixArgs)
+
+-- | Call a LaTeX command with the first 'n' arguments as optional ones,
+-- followed by fixed arguments. Most LaTeX commands are structured with first a
+-- sequence of optional arguments, followed by a sequence of fixed arguments.
+optFixComm :: LaTeXC l => String -> Int -> [l] -> l
+optFixComm str k = liftListL (TeXComm str . optFixArgs k)
+
+-- | Create a LaTeX environment where all the arguments in the list are fixed
+--   arguments.
+fixEnv :: LaTeXC l => String -> [l] -> l -> l
+fixEnv str args inner = liftListL (\(inn:as) -> TeXEnv str (fixArgs as) inn) (inner:args)
+
 -- | A simple (without arguments) and handy command generator
 --   using the name of the command.
 --
@@ -81,7 +131,7 @@
 -- > comm1 str = liftL $ \l -> TeXComm str [FixArg l]
 --
 comm1 :: LaTeXC l => String -> l -> l
-comm1 str = liftL $ \l -> TeXComm str [FixArg l]
+comm1 str l1 = fixComm str [l1]
 
 -- | A two parameter command generator using the name of the command.
 --   The parameters will be rendered as fixed arguments.
@@ -89,16 +139,65 @@
 -- > comm2 str = liftL2 $ \l1 l2 -> TeXComm str [FixArg l1, FixArg l2]
 --
 comm2 :: LaTeXC l => String -> l -> l -> l
-comm2 str = liftL2 $ \l1 l2 -> TeXComm str [FixArg l1, FixArg l2]
+comm2 str l1 l2 = fixComm str [l1, l2]
 
 -- | A three parameter command generator using the name of the command.
 --   The parameters will be rendered as fixed arguments.
 --
--- > comm3 str = liftL2 $ \l1 l2 l3 -> TeXComm str [FixArg l1, FixArg l2, FixArg l3]
+-- > comm3 str = liftL3 $ \l1 l2 l3 -> TeXComm str [FixArg l1, FixArg l2, FixArg l3]
 --
 comm3 :: LaTeXC l => String -> l -> l -> l -> l
-comm3 str = liftL3 $ \l1 l2 l3 -> TeXComm str [FixArg l1, FixArg l2, FixArg l3]
+comm3 str l1 l2 l3 = fixComm str [l1, l2, l3]
 
+-- | A four parameter command generator using the name of the command.
+--   The parameters will be rendered as fixed arguments.
+--
+-- > comm4 str = liftL4 $ \l1 l2 l3 l4 -> TeXComm str [FixArg l1, FixArg l2, FixArg l3, FixArg l4]
+--
+comm4 :: LaTeXC l => String -> l -> l -> l -> l -> l
+comm4 str l1 l2 l3 l4 = fixComm str [l1, l2, l3, l4]
+
+-- | A five parameter command generator using the name of the command.
+--   The parameters will be rendered as fixed arguments.
+--
+-- > comm5 str = liftL5 $ \l1 l2 l3 l4 l5 -> TeXComm str [FixArg l1, FixArg l2, FixArg l3, FixArg l4, FixArg l5]
+--
+comm5 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l
+comm5 str l1 l2 l3 l4 l5 = fixComm str [l1, l2, l3, l4, l5]
+
+-- | A six parameter command generator using the name of the command.
+--   The parameters will be rendered as fixed arguments.
+--
+-- > comm6 str = liftL6 $ \l1 l2 l3 l4 l5 l6 -> TeXComm str [FixArg l1, FixArg l2, FixArg l3, FixArg l4, FixArg l5, FixArg l6]
+--
+comm6 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l -> l
+comm6 str l1 l2 l3 l4 l5 l6 = fixComm str [l1, l2, l3, l4, l5, l6]
+
+-- | A seven parameter command generator using the name of the command.
+--   The parameters will be rendered as fixed arguments.
+--
+-- > comm7 str = liftL7 $ \l1 l2 l3 l4 l5 l6 l7 -> TeXComm str [FixArg l1, FixArg l2, FixArg l3, FixArg l4, FixArg l5, FixArg l6, FixArg l7]
+--
+comm7 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l -> l -> l
+comm7 str l1 l2 l3 l4 l5 l6 l7 = fixComm str [l1, l2, l3, l4, l5, l6, l7]
+
+-- | An eight parameter command generator using the name of the command.
+--   The parameters will be rendered as fixed arguments.
+--
+-- > comm8 str = liftL8 $ \l1 l2 l3 l4 l5 l6 l7 l8 -> TeXComm str [FixArg l1, FixArg l2, FixArg l3, FixArg l4, FixArg l5, FixArg l6, FixArg l7, FixArgs l8]
+--
+comm8 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l -> l -> l -> l
+comm8 str l1 l2 l3 l4 l5 l6 l7 l8 = fixComm str [l1, l2, l3, l4, l5, l6, l7, l8]
+
+-- | A nine parameter command generator using the name of the command.
+--   The parameters will be rendered as fixed arguments.
+--
+-- > comm9 str = liftL9 $ \l1 l2 l3 l4 l5 l6 l7 l8 l9 -> TeXComm str [FixArg l1, FixArg l2, FixArg l3, FixArg l4, FixArg l5, FixArg l6, FixArg l7, FixArgs l8, l9]
+--
+comm9 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l -> l -> l -> l -> l
+comm9 str l1 l2 l3 l4 l5 l6 l7 l8 l9 = fixComm str [l1, l2, l3, l4, l5, l6, l7, l8, l9]
+
+
 -- | Like 'comm0' but using 'TeXCommS', i.e. no \"{}\" will be inserted to protect
 -- the command's end.
 --
@@ -106,6 +205,56 @@
 --
 commS :: LaTeXC l => String -> l
 commS = fromLaTeX . TeXCommS
+
+-- | Define an environment, without any parameters that are passed to the
+--   environment.
+env0 :: LaTeXC l => String -> l -> l
+env0 str = fixEnv str []
+
+-- | Define an environment, with one fixed parameter that is passed to the
+--   environment.
+env1 :: LaTeXC l => String -> l -> l -> l
+env1 str l1 = fixEnv str [l1]
+
+-- | Define an environment, with two fixed parameters that is passed to the
+--   environment.
+env2 :: LaTeXC l => String -> l -> l -> l -> l
+env2 str l1 l2 = fixEnv str [l1, l2]
+
+-- | Define an environment, with three fixed parameters that is passed to the
+--   environment.
+env3 :: LaTeXC l => String -> l -> l -> l -> l -> l
+env3 str l1 l2 l3 = fixEnv str [l1, l2, l3]
+
+-- | Define an environment, with four fixed parameters that is passed to the
+--   environment.
+env4 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l
+env4 str l1 l2 l3 l4 = fixEnv str [l1, l2, l3, l4]
+
+-- | Define an environment, with five fixed parameters that is passed to the
+--   environment.
+env5 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l -> l
+env5 str l1 l2 l3 l4 l5 = fixEnv str [l1, l2, l3, l4, l5]
+
+-- | Define an environment, with six fixed parameters that is passed to the
+--   environment.
+env6 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l -> l -> l
+env6 str l1 l2 l3 l4 l5 l6 = fixEnv str [l1, l2, l3, l4, l5, l6]
+
+-- | Define an environment, with seven fixed parameters that is passed to the
+--   environment.
+env7 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l -> l -> l -> l
+env7 str l1 l2 l3 l4 l5 l6 l7 = fixEnv str [l1, l2, l3, l4, l5, l6, l7]
+
+-- | Define an environment, with eight fixed parameters that is passed to the
+--   environment.
+env8 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l -> l -> l -> l -> l
+env8 str l1 l2 l3 l4 l5 l6 l7 l8 = fixEnv str [l1, l2, l3, l4, l5, l6, l7, l8]
+
+-- | Define an environment, with nine fixed parameters that is passed to the
+--   environment.
+env9 :: LaTeXC l => String -> l -> l -> l -> l -> l -> l -> l -> l -> l -> l -> l
+env9 str l1 l2 l3 l4 l5 l6 l7 l8 l9 = fixEnv str [l1, l2, l3, l4, l5, l6, l7, l8, l9]
 
 -- | A lifted version of the 'TeXBraces' constructor.
 --
diff --git a/Text/LaTeX/Base/Commands.hs b/Text/LaTeX/Base/Commands.hs
--- a/Text/LaTeX/Base/Commands.hs
+++ b/Text/LaTeX/Base/Commands.hs
@@ -711,8 +711,9 @@
 nolinebreak :: LaTeXC l => l -> l
 nolinebreak = liftL $ \l -> TeXComm "nolinebreak" [OptArg l]
 
-pagebreak :: LaTeXC l => l -> l
-pagebreak = liftL $ \l -> TeXComm "pagebreak" [OptArg l]
+pagebreak :: LaTeXC l => Maybe l -> l
+pagebreak = maybe (comm0 "pagebreak")
+            $ liftL $ \l -> TeXComm "pagebreak" [OptArg l]
 
 nopagebreak :: LaTeXC l => Maybe l -> l
 nopagebreak = maybe (comm0 "nopagebreak")
@@ -1083,7 +1084,7 @@
               -> Matrix a -- ^ Matrix of data
               -> l -- ^ Data organized in a tabular environment
 matrixTabular ts m =
-  let spec = VerticalLine : (intersperse VerticalLine $ replicate (ncols m) CenterColumn) ++ [VerticalLine]
+  let spec = VerticalLine : intersperse VerticalLine (replicate (ncols m) CenterColumn) ++ [VerticalLine]
   in  tabular Nothing spec $ mconcat
         [ hline
         , foldl1 (&) ts
diff --git a/Text/LaTeX/Base/Math.hs b/Text/LaTeX/Base/Math.hs
--- a/Text/LaTeX/Base/Math.hs
+++ b/Text/LaTeX/Base/Math.hs
@@ -522,9 +522,7 @@
 notop :: LaTeXC l =>
          (l -> l -> l)
       ->  l -> l -> l
-notop op =
- \l1 l2 ->
-   (l1 <> commS "not") `op` l2
+notop op l1 l2 = (l1 <> commS "not") `op` l2
 
 infixl 6 +-, -+
 
diff --git a/Text/LaTeX/Base/Parser.hs b/Text/LaTeX/Base/Parser.hs
--- a/Text/LaTeX/Base/Parser.hs
+++ b/Text/LaTeX/Base/Parser.hs
@@ -51,10 +51,12 @@
 import           Text.Parsec hiding ((<|>),many)
 import           Text.Parsec.Error
 import           Data.Char (toLower,digitToInt)
+import           Data.Functor(($>))
 #if !MIN_VERSION_base(4,11,0)
 import           Data.Monoid
 #endif
 import           Data.Maybe (fromMaybe)
+import           Data.Set(Set, fromList, member)
 import qualified Data.Text as T 
 
 import           Control.Applicative
@@ -68,7 +70,7 @@
 ------------------------------------------------------------------------
 
 -- | Configuration for the LaTeX parser.
-data ParserConf = ParserConf
+newtype ParserConf = ParserConf
   { -- | This is the list of names of the environments such that
     --   their content will be parsed verbatim.
     verbatimEnvironments :: [String]
@@ -125,19 +127,20 @@
     ]
 -- Note: text stops on ']'; if the other parsers fail on the rest
 --       text2 handles it, starting with ']' 
-  
+
 ------------------------------------------------------------------------
 -- Text
 ------------------------------------------------------------------------
+nottext :: Set Char
+nottext = fromList "$%\\{]}"
+
 text :: Parser LaTeX
 text = do
   mbC <- peekChar
-  let nottext :: [Char]
-      nottext = "$%\\{]}"
   case mbC of
     Nothing -> fail "text: Empty input."
-    Just c | c `elem` nottext -> fail "not text"
-           | otherwise          -> TeXRaw <$> takeTill (`elem` nottext)
+    Just c | c `member` nottext -> fail "not text"
+           | otherwise          -> TeXRaw <$> takeTill (`member` nottext)
 
 ------------------------------------------------------------------------
 -- Text without stopping on ']'
@@ -346,10 +349,10 @@
 specials = "'(),.-\"!^$&#{}%~|/:;=[]\\` "
 
 peekChar :: Parser (Maybe Char)
-peekChar = Just <$> (try $ lookAhead anyChar) <|> pure Nothing
+peekChar = Just <$> try (lookAhead anyChar) <|> pure Nothing
 
 atEnd :: Parser Bool
-atEnd = (eof *> pure True) <|> pure False
+atEnd = (eof $> True) <|> pure False
 
 takeTill :: (Char -> Bool) -> Parser Text
 takeTill p = T.pack <$> many (satisfy (not . p))
diff --git a/Text/LaTeX/Base/Pretty.hs b/Text/LaTeX/Base/Pretty.hs
--- a/Text/LaTeX/Base/Pretty.hs
+++ b/Text/LaTeX/Base/Pretty.hs
@@ -63,7 +63,7 @@
   let ls = Data.Text.lines t
   in  if null ls
          then pretty '%' <> hardline
-         else (align $ vsep $ fmap (pretty . ("% "++) . unpack) ls) <> hardline
+         else align (vsep $ fmap (pretty . ("% "++) . unpack) ls) <> hardline
 docLaTeX (TeXSeq l1 l2) = docLaTeX l1 <> docLaTeX l2
 docLaTeX TeXEmpty = mempty
 
diff --git a/Text/LaTeX/Base/Syntax.hs b/Text/LaTeX/Base/Syntax.hs
--- a/Text/LaTeX/Base/Syntax.hs
+++ b/Text/LaTeX/Base/Syntax.hs
@@ -109,14 +109,6 @@
  --
  mappend x y = TeXSeq x y
 
--- Since GHC starting from 7.4 provides (<>) as synonym to 'mappend' (see "Data.Monoid"),
--- we avoid an overlapping definition with a CPP conditional.
-#if __GLASGOW_HASKELL__ < 704
--- | Alias for 'mappend'.
-(<>) :: Monoid a => a -> a -> a
-(<>) = mappend
-#endif
-
 instance Semigroup.Semigroup LaTeX where
   (<>) = mappend
 
@@ -180,7 +172,7 @@
 matchCommand f (TeXComm str as) =
   let xs = concatMap (matchCommandArg f) as
   in  if f str then (str,as) : xs else xs
-matchCommand f (TeXCommS str) = if f str then [(str,[])] else []
+matchCommand f (TeXCommS str) = [(str, []) | f str]
 matchCommand f (TeXEnv _ as l) =
   let xs = concatMap (matchCommandArg f) as
   in  xs ++ matchCommand f l
@@ -324,9 +316,9 @@
             TeXEnv <$> arbitraryName <*> vectorOf m arbitrary <*> arbitrary
     4 -> if inDollar
             then arbitraryLaTeX True
-            else do do m <- choose (0,3)
-                       let t = [Parentheses,Square,Dollar,DoubleDollar] !! m
-                       TeXMath <$> pure t <*> arbitraryLaTeX (t == Dollar || t == DoubleDollar)
+            else do m <- choose (0,3)
+                    let t = [Parentheses,Square,Dollar,DoubleDollar] !! m
+                    TeXMath <$> pure t <*> arbitraryLaTeX (t == Dollar || t == DoubleDollar)
     5 -> TeXLineBreak <$> arbitrary <*> arbitrary
     6 -> TeXBraces <$> arbitrary
     7 -> TeXComment <$> arbitraryRaw
diff --git a/Text/LaTeX/Base/Types.hs b/Text/LaTeX/Base/Types.hs
--- a/Text/LaTeX/Base/Types.hs
+++ b/Text/LaTeX/Base/Types.hs
@@ -37,10 +37,10 @@
 labelName (Label str) = str
 
 instance Render Label where
- render (Label str) = fromString str
+    render (Label str) = fromString str
 
 instance IsString Label where
- fromString = createLabel
+    fromString = createLabel
 
 -- | Vertical position. 'Here' and 'ForcePos' are used with @table@ environments.
 data Pos = Bottom | Center | Top | Here | ForcePos deriving Show
diff --git a/Text/LaTeX/Base/Writer.hs b/Text/LaTeX/Base/Writer.hs
--- a/Text/LaTeX/Base/Writer.hs
+++ b/Text/LaTeX/Base/Writer.hs
@@ -1,4 +1,3 @@
-
 {-# LANGUAGE TypeFamilies, CPP #-}
 
 -- | The writer monad applied to 'LaTeX' values. Useful to compose 'LaTeX' values
@@ -75,15 +74,14 @@
 import Text.LaTeX.Base.Warnings (Warning,checkAll,check)
 
 -- | 'WriterT' monad transformer applied to 'LaTeX' values.
-newtype LaTeXT m a =
-  LaTeXT { unwrapLaTeXT :: WriterT LaTeX m a }
+newtype LaTeXT m a = LaTeXT { unwrapLaTeXT :: WriterT LaTeX m a }
 
 instance Functor f => Functor (LaTeXT f) where
- fmap f = LaTeXT . fmap f . unwrapLaTeXT
+    fmap f = LaTeXT . fmap f . unwrapLaTeXT
 
 instance Applicative f => Applicative (LaTeXT f) where
- pure = LaTeXT . pure
- (LaTeXT f) <*> (LaTeXT x) = LaTeXT $ f <*> x
+    pure = LaTeXT . pure
+    (LaTeXT f) <*> (LaTeXT x) = LaTeXT $ f <*> x
 
 -- | Type synonym for empty 'LaTeXT' computations.
 type LaTeXT_ m = LaTeXT m ()
@@ -114,7 +112,6 @@
   a <- c
   let LaTeXT c' = f a
   c'
- fail = return . error
 
 instance MonadIO m => MonadIO (LaTeXT m) where
  liftIO = lift . liftIO
diff --git a/Text/LaTeX/Packages/Acronym.hs b/Text/LaTeX/Packages/Acronym.hs
new file mode 100644
--- /dev/null
+++ b/Text/LaTeX/Packages/Acronym.hs
@@ -0,0 +1,258 @@
+{-# LANGUAGE OverloadedStrings, CPP #-}
+
+-- | Add acronyms to your documents using this module.
+--
+--   Define and render acronyms in a document, where the first occurrance is the
+--   long variant, and the next ones are the shorter variant.
+module Text.LaTeX.Packages.Acronym
+ ( -- * Acronym package
+   pacronym
+   -- * Package options
+ , footnote, nohyperlinks, printonlyused, withpage, smaller, dua, nolist
+ -- * Types
+ , Acronym(..)
+ -- functions
+ , ac, acf, acs, acl, acp, acfp, acsp, aclp, acfi, acsu, aclu, iac, iac2
+ , ac', acf', acs', acl', acp', acfp', acsp', aclp', acfi', acsu', aclu', iac', iac2'
+ , acresetall, acused
+ , acroextra
+ , acronym
+ , acro, acro'
+ , acroM, acroM'
+   ) where
+
+import Data.String(IsString(fromString))
+
+import Text.LaTeX.Base.Class(LaTeXC, comm0, comm1, comm2, liftL, liftL2)
+import Text.LaTeX.Base.Syntax(LaTeX(TeXComm, TeXEnv), TeXArg(FixArg, OptArg))
+import Text.LaTeX.Base.Types(PackageName)
+import Text.LaTeX.Base.Writer(LaTeXT)
+
+-- | The 'pacronym' package.
+--
+-- > usepackage [] pacronym
+pacronym :: PackageName
+pacronym = "acronym"
+
+-- | Redefines the `\acf` and `\acfp` commands making the full
+--   name appear as a footnote
+footnote :: LaTeXC l => l
+footnote = "footnote"
+
+-- | If hyperref is loaded, all acronyms will link to their glossary entry. With
+--   the `nohyperlinks` option, these links are suppressed.
+nohyperlinks :: LaTeXC l => l
+nohyperlinks = "nohyperlinks"
+
+-- | We need a marker which is set if the option `printonlyused` was used.
+printonlyused :: LaTeXC l => l
+printonlyused = "printonlyused"
+
+-- | A marker which tells us to print page numbers.
+withpage :: LaTeXC l => l
+withpage = "withpage"
+
+-- | The option `smaller` leads to a redefinition of `\acsfont`. We want to make
+--   the acronym appear smaller. Since this should be done in a
+--   context-sensitive way, we rely on the macro \textsmaller provided by the
+--   `relsize` package. As `\RequiredPackage` cannot be used inside
+--   `\DeclareOption`, we need a boolean variable.
+smaller :: LaTeXC l => l
+smaller = "smaller"
+
+-- | The option `dua` stands for "don't use acronyms". It leads to a
+--   redefinition of `\ac` and `\acp` making the full name appear all the time
+--   and suppressing all acronyms but the explicitly requested by `\acf` and
+--   `\acfp`.
+dua :: LaTeXC l => l
+dua = "dua"
+
+-- | The option `nolist` stands for "don't write the list of acronyms".
+nolist :: LaTeXC l => l
+nolist = "nolist"
+
+-- | An acronym type with a label, this is used to generate commands linked to
+--   this acronym.
+newtype Acronym = Acronym { acronymLabel :: String }
+
+_acronymLabel :: IsString s => Acronym -> s
+_acronymLabel = fromString . acronymLabel
+
+_acronymC1 :: LaTeXC l => String -> Acronym -> l
+_acronymC1 = (. _acronymLabel) . comm1
+
+-- | Enter an acronym inside the text. The first time the acronym is used, it
+--   will specify the full name, and between parenthesis, the short name. If you
+--   specified the `footnote` option, it will print the short name, and add a
+--   footnote with the long name. The next time, only the short time is printed.
+ac :: LaTeXC l => Acronym -> l
+ac = _acronymC1 "ac"
+
+-- | You can use this command to later in the text again print the full name of
+--   the acronym, this stands for "full acronym", it always prints the full
+--   name, and the acronym between parenthesis.
+acf :: LaTeXC l => Acronym -> l
+acf = _acronymC1 "acf"
+
+-- | This will enter the short version of the acronym inside the text.
+acs :: LaTeXC l => Acronym -> l
+acs = _acronymC1 "acs"
+
+-- | This will enter the expanded version of the acronym in the text, without
+--   mentioning the acronym between parenthesis.
+acl :: LaTeXC l => Acronym -> l
+acl = _acronymC1 "acl"
+
+-- | This works the same way as `ac`, except that it will make the short and the
+--   long forms into plurals.
+acp :: LaTeXC l => Acronym -> l
+acp = _acronymC1 "acp"
+
+-- | This works the same way as `acf`, except tah it will make the short and
+--   long forms into plurals.
+acfp :: LaTeXC l => Acronym -> l
+acfp = _acronymC1 "acfp"
+
+-- | Works the same way as `acs`, but makes the short form into a plural.
+acsp :: LaTeXC l => Acronym -> l
+acsp = _acronymC1 "acsp"
+
+-- | Works the same way as `acl`, but makes the long form into a plural.
+aclp :: LaTeXC l => Acronym -> l
+aclp = _acronymC1 "aclp"
+
+-- | Prints the full name acronym in italics and the abbreviated form in an
+-- upshaped form.
+acfi :: LaTeXC l => Acronym -> l
+acfi = _acronymC1 "acfi"
+
+-- | Prints the short form of the acronym, and marks it as used.
+acsu :: LaTeXC l => Acronym -> l
+acsu = _acronymC1 "acsu"
+
+-- | Prints the long form of the acronym and marks it as used.
+aclu :: LaTeXC l => Acronym -> l
+aclu = _acronymC1 "aclu"
+
+-- | Works the same way as the `ac` command, but prefixes it with an appropriate
+-- indefinite article.
+iac :: LaTeXC l => Acronym -> l
+iac = _acronymC1 "iac"
+
+-- | Works the same way as the `ac` command, but prefixes it with an appropriate
+-- upper case indefinite article.
+iac2 :: LaTeXC l => Acronym -> l
+iac2 = _acronymC1 "Iac"
+
+-- | Enter an acronym inside the text. It will specify the full name, and
+--   between parenthesis, the short name. If you specified the `footnote`
+--   option, it will print the short name, and add a footnote with the long
+--   name. This does not mark the acronym as used.
+ac' :: LaTeXC l => Acronym -> l
+ac' = _acronymC1 "ac*"
+
+-- | You can use this command to later in the text again print the full name of
+--   the acronym, this stands for "full acronym", it always prints the full
+--   name, and the acronym between parenthesis. This does not mark the
+--   acronym as used.
+acf' :: LaTeXC l => Acronym -> l
+acf' = _acronymC1 "acf*"
+
+-- | This will enter the short version of the acronym inside the text.
+-- This does not mark the acronym as used.
+acs' :: LaTeXC l => Acronym -> l
+acs' = _acronymC1 "acs*"
+
+-- | This will enter the expanded version of the acronym in the text, without
+--   mentioning the acronym between parenthesis. This does not mark the acronym
+--   as used.
+acl' :: LaTeXC l => Acronym -> l
+acl' = _acronymC1 "acl*"
+
+-- | This works the same way as `ac`, except that it will make the short and the
+--   long forms into plurals. This does not mark the acronym as used.
+acp' :: LaTeXC l => Acronym -> l
+acp' = _acronymC1 "acp*"
+
+-- | This works the same way as `acf`, except tah it will make the short and
+--   long forms into plurals. This does not mark the acronym as used.
+acfp' :: LaTeXC l => Acronym -> l
+acfp' = _acronymC1 "acfp*"
+
+-- | Works the same way as `acs`, but makes the short form into a plural. This
+--   does not mark the acronym as used.
+acsp' :: LaTeXC l => Acronym -> l
+acsp' = _acronymC1 "acsp*"
+
+-- | Works the same way as `acl`, but makes the long form into a plural. This
+--   does not mark the acronym as used.
+aclp' :: LaTeXC l => Acronym -> l
+aclp' = _acronymC1 "aclp*"
+
+-- | Prints the full name acronym in italics and the abbreviated form in an
+-- upshaped form. This does not mark the acronym as used.
+acfi' :: LaTeXC l => Acronym -> l
+acfi' = _acronymC1 "acfi*"
+
+-- | Prints the short form of the acronym, and marks it as used. This does not
+--   mark the acronym as used.
+acsu' :: LaTeXC l => Acronym -> l
+acsu' = _acronymC1 "acsu*"
+
+-- | Prints the long form of the acronym and marks it as used. This does not mark
+--   the acronym as used.
+aclu' :: LaTeXC l => Acronym -> l
+aclu' = _acronymC1 "aclu*"
+
+-- | Works the same way as the `ac` command, but prefixes it with an appropriate
+-- indefinite article. This does not mark the acronym as used.
+iac' :: LaTeXC l => Acronym -> l
+iac' = _acronymC1 "iac*"
+
+-- | Works the same way as the `ac` command, but prefixes it with an appropriate
+-- upper case indefinite article. This does not mark the acronym as used.
+iac2' :: LaTeXC l => Acronym -> l
+iac2' = _acronymC1 "Iac*"
+
+-- | The memory of the marco `ac` is flushed, afterwards, `ac` will print the
+--   full name of any acronym, and the acronym within parenthesis.
+acresetall :: LaTeXC l => l
+acresetall = comm0 "acresetall"
+
+-- | Marks an acronym as useed, as if it has been called with `ac`, but without
+--   printing anything. In the future, only the short form of the acronym will
+--   be printed. `acresetall` undoes this.
+acused :: LaTeXC l => Acronym -> l
+acused = _acronymC1 "acused"
+
+-- | This can be used inside the `acro` part to add extra data to the list of
+--   acrynyms, this will *not* be included when rendering the acronym in the
+--   document itself.
+acroextra :: LaTeXC l => l -> l
+acroextra = comm1 "acroextra"
+
+-- | Define an acronym environment to write the acronym definitions to.
+acronym :: LaTeXC l => l -> l
+acronym = liftL (TeXEnv "acronym" [])
+
+-- | Define an acronym with a label and both a short, and a long name. This
+--   returns the LaTeX code to define the acronym, and the `Acronym` object
+--   to use in the rest of the code.
+acro :: LaTeXC l => String -> l -> l -> (l, Acronym)
+acro str l2 l3 = (liftL2 (\la lb -> TeXComm "acro" [FixArg (fromString str), OptArg la, FixArg lb]) l2 l3, Acronym str)
+
+-- | The monadic variant of the `acro` function where the `Acronym` is returned
+--   as a result of the definition.
+acroM :: Monad m => String -> LaTeXT m () -> LaTeXT m () -> LaTeXT m Acronym
+acroM str l2 l3 = uncurry (flip (fmap . const)) (acro str l2 l3)
+
+-- | Define an acronym with a label, and only a long name. This returns the
+--   LaTeX code to define the acronym, and the `Acronym` object to use in the
+--   rest of the code.
+acro' :: LaTeXC l => String -> l -> (l, Acronym)
+acro' str l = (comm2 "acro" (fromString str) l, Acronym str)
+
+-- | The monadic variant of the `acro'` function, where the `Acronym` is
+--   returned as result of the definition.
+acroM' :: Monad m => String -> LaTeXT m () -> LaTeXT m Acronym
+acroM' str l2 = uncurry (flip (fmap . const)) (acro' str l2)
diff --git a/Text/LaTeX/Packages/BibLaTeX.hs b/Text/LaTeX/Packages/BibLaTeX.hs
--- a/Text/LaTeX/Packages/BibLaTeX.hs
+++ b/Text/LaTeX/Packages/BibLaTeX.hs
@@ -1,4 +1,7 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DeriveGeneric     #-}
+{-# LANGUAGE DeriveFunctor     #-}
+{-# LANGUAGE FlexibleContexts  #-}
 
 -- | <https://ctan.org/tex-archive/macros/latex/contrib/biblatex BibLaTeX>
 --   is a reference-citation package using @.bib@ files (BibTeX) but no extra style-files.
@@ -8,14 +11,43 @@
  , addbibresource
  , cite
  , printbibliography
+ -- * Automatic bibliography retrieval
+ , documentWithDOIReferences
+ , citeDOI
+ , textc
+ , textC
+ , DOIReference
+ , ReferenceQueryT
+ , masterBibFile
  ) where
 
-import Text.LaTeX.Base.Syntax
-import Text.LaTeX.Base.Class
+import Text.LaTeX.Base.Syntax hiding ((<>))
+import Text.LaTeX.Base.Class (LaTeXC(..), liftL, fromLaTeX, comm0, raw)
 import Text.LaTeX.Base.Render
 import Text.LaTeX.Base.Types
-import Text.LaTeX.Base.Commands (cite)
+import Text.LaTeX.Base.Commands (cite, footnote, document)
 
+import Data.Char (toLower)
+import qualified Data.Semigroup as SG
+import GHC.Generics (Generic)
+import qualified Data.Traversable as Tr
+
+import qualified Data.Map as Map
+import Data.Maybe (catMaybes)
+import Data.Hashable (hash)
+import Numeric (showHex)
+
+import qualified Data.List as List
+
+import Control.Applicative
+import Control.Monad (forM)
+import Control.Monad.IO.Class
+
+import qualified Text.BibTeX.Entry as BibTeX
+import qualified Text.BibTeX.Format as BibTeX
+import qualified Text.BibTeX.Parse as BibTeX (file)
+import qualified Text.Parsec.String as Parsec
+
 -- | BibLaTeX package. Use it to import it like this:
 --
 -- > usepackage [] biblatex
@@ -29,3 +61,158 @@
 printbibliography :: LaTeXC l => l
 printbibliography = comm0 "printbibliography"
 
+
+documentWithDOIReferences :: (MonadIO m, LaTeXC (m ()), SG.Semigroup (m ()), r ~ DOIReference)
+  => (r -> m (Maybe BibTeX.T)) -- ^ Reference-resolver function, for looking up BibTeX
+                               --   entries for a given DOI.
+                               --   If the DOI cannot be looked up (@Nothing@), we just
+                               --   include a footnote with a synopsis and the DOI in
+                               --   literal form. (Mostly intended to ease offline editing.)
+  -> ReferenceQueryT r m ()    -- ^ The document content, possibly containing citations
+                               --   in DOI-only form.
+  -> m ()                      -- ^ LaTeX rendition. The content will already be wrapped
+                               --   in @\\begin…end{document}@ here and an
+                               --   automatically-generated @.bib@ file included, but
+                               --   you still need to 'usepackage' 'biblatex' yourself.
+documentWithDOIReferences resolver (ReferenceQueryT refq) = do
+    (allRefs, (), useRefs) <- refq
+    resolved <- fmap catMaybes . forM (allRefs[]) $ \r -> do
+       r' <- resolver r
+       return $ case r' of
+         Just entry -> Just (r, entry)
+         Nothing -> Nothing
+    let refsMap = Map.fromList resolved
+        bibfileConts = unlines $ BibTeX.entry . snd <$> Map.toList refsMap
+        bibfileName = showHex (abs $ hash bibfileConts) $ ".bib"
+    liftIO $ writeFile bibfileName bibfileConts
+    () <- addbibresource bibfileName
+    document . useRefs $ \r flavour -> case Map.lookup r refsMap of
+        Just a -> let citeC = liftL $ \l -> (`TeXComm`[FixArg l]) $ case flavour of
+                        Flavour_cite      -> "cite" 
+                        Flavour_Cite      -> "Cite"
+                        Flavour_parencite -> "parencite"
+                        Flavour_Parencite -> "Parencite"
+                        Flavour_footcite  -> "footcite"
+                        Flavour_Footcite  -> "Footcite"
+                        Flavour_textcite  -> "textcite"
+                        Flavour_Textcite  -> "Textcite"
+                        Flavour_smartcite -> "smartcite"
+                        Flavour_Smartcite -> "Smartcite"
+                  in citeC . raw . fromString $ BibTeX.identifier a
+        Nothing -> makeshift r
+ where makeshift :: (LaTeXC l, SG.Semigroup l) => DOIReference -> l
+       makeshift (DOIReference doi synops) = footnote $
+           fromLaTeX synops SG.<> ". DOI:" SG.<> fromString doi
+    
+
+type PlainDOI = String
+
+data DOIReference = DOIReference {
+       _referenceDOI :: PlainDOI
+     , _referenceSynopsis :: LaTeX
+     } deriving (Generic)
+instance Eq DOIReference where
+  DOIReference doi₀ _ == DOIReference doi₁ _ = doi₀ == doi₁
+instance Ord DOIReference where
+  compare (DOIReference doi₀ _) (DOIReference doi₁ _) = compare doi₀ doi₁
+
+type DList r = [r] -> [r]
+
+data CitationFlavour
+       = Flavour_cite
+       | Flavour_Cite
+       | Flavour_parencite
+       | Flavour_Parencite
+       | Flavour_footcite
+       | Flavour_Footcite
+       | Flavour_textcite
+       | Flavour_Textcite
+       | Flavour_smartcite
+       | Flavour_Smartcite
+     deriving (Eq, Ord, Show)
+
+newtype ReferenceQueryT r m a = ReferenceQueryT {
+       runReferenceQueryT :: m (DList r, a, (r -> CitationFlavour -> m ()) -> m ())
+     }
+  deriving (Generic, Functor)
+
+instance Applicative m => Applicative (ReferenceQueryT r m) where
+  pure x = ReferenceQueryT . pure $ (id, x, const $ pure ())
+  ReferenceQueryT refqf <*> ReferenceQueryT refqx = ReferenceQueryT $
+       liftA2 (\(urefsf, f, refref)
+                (urefsx, x, refrex)
+                  -> ( urefsf . urefsx
+                     , f x
+                     , \resolv -> mappend <$> refref resolv <*> refrex resolv ) )
+              refqf refqx
+instance Monad m => Monad (ReferenceQueryT r m) where
+  return = pure
+  ReferenceQueryT refsx >>= f
+     = ReferenceQueryT $ refsx >>= \(urefsx, x, refrex)
+           -> case f x of
+                ReferenceQueryT refsfx
+                  -> (\(urefsfx,fx,refrefx)
+                        -> ( urefsx.urefsfx
+                           , fx
+                           , \resolve -> mappend <$> refrex resolve <*> refrefx resolve ))
+                     <$> refsfx
+instance MonadIO m => MonadIO (ReferenceQueryT r m) where
+  liftIO a = ReferenceQueryT $ (\r -> (id, r, const $ pure ())) <$> liftIO a
+
+instance (Functor m, Monoid (m a), IsString (m ()), a ~ ())
+           => IsString (ReferenceQueryT r m a) where
+  fromString s = ReferenceQueryT $ (\a -> (id, a, const $ fromString s)) <$> mempty
+
+instance (Applicative m, SG.Semigroup (m a), a ~ ())
+             => SG.Semigroup (ReferenceQueryT r m a) where
+  ReferenceQueryT p <> ReferenceQueryT q
+      = ReferenceQueryT $ liftA2 (\(rp,(),ρp) (rq,(),ρq)
+                                     -> (rp.rq,(),liftA2(liftA2 (SG.<>))ρp ρq)) p q
+
+instance (Applicative m, SG.Semigroup (m a), Monoid (m a), a ~ ())
+    => Monoid (ReferenceQueryT r m a) where
+  mempty = ReferenceQueryT $ (\a -> (id, a, mempty)) <$> mempty
+  mappend = (SG.<>)
+
+instance (Applicative m, LaTeXC (m a), SG.Semigroup (m a), a ~ ())
+             => LaTeXC (ReferenceQueryT r m a) where
+  liftListL f xs = ReferenceQueryT $
+    (\components -> case List.unzip3 components of
+          (refs, _, rebuilds) -> ( foldr (.) id refs
+                                 , ()
+                                 , \resolve -> liftListL f $ ($ resolve)<$>rebuilds )
+       ) <$> Tr.traverse runReferenceQueryT xs
+
+citeDOI :: (Functor m, Monoid (m ()), IsString (m ()))
+        => PlainDOI  -- ^ The unambiguous document identifier.
+        -> String    -- ^ Synopsis of the cited work, in the form
+                     --   @"J Doe et al 1950: Investigation of a Foo"@;
+                     --   this is strictly speaking optional, the synopsis will /not/
+                     --   be included in the final document (provided the DOI
+                     --   can be properly resolved).
+        -> ReferenceQueryT DOIReference m ()
+citeDOI doi synops = ReferenceQueryT $ (\a -> ( (r :), a, \f -> f r Flavour_cite ))
+                       <$> mempty
+ where r = DOIReference doi $ fromString synops
+
+-- | Transform a citation into @\\textcite@, i.e. so that it can be used as a noun in a sentence.
+textc :: Functor m => ReferenceQueryT DOIReference m () -> ReferenceQueryT DOIReference m ()
+textc (ReferenceQueryT y) = ReferenceQueryT
+        $ (\(r,m,a) -> (r, m, \f -> a (\x _ -> f x Flavour_textcite))) <$> y
+
+-- | Transform a citation into @\\Textcite@, i.e. so that it can be used as the first word in a sentence.
+textC :: Functor m => ReferenceQueryT DOIReference m () -> ReferenceQueryT DOIReference m ()
+textC (ReferenceQueryT y) = ReferenceQueryT
+        $ (\(r,m,a) -> (r, m, \f -> a (\x _ -> f x Flavour_Textcite))) <$> y
+
+masterBibFile :: MonadIO m
+      => FilePath    -- ^ A @.bib@ file containing entries for all relevant literature.
+      -> (DOIReference -> m (Maybe BibTeX.T))
+                     -- ^ Lookup-function, suitable for 'documentWithDOIReferences'.
+masterBibFile master (DOIReference doi _) = do
+   entries <- liftIO $ BibTeX.file `Parsec.parseFromFile` master
+   return $ case entries of
+     Right bibs -> List.find hasThisDOI bibs
+     Left err   -> error $ show err
+ where hasThisDOI bib = (map toLower <$> List.lookup "doi" (BibTeX.fields bib))
+                          == Just (toLower<$>doi)
diff --git a/Text/LaTeX/Packages/Graphicx.hs b/Text/LaTeX/Packages/Graphicx.hs
--- a/Text/LaTeX/Packages/Graphicx.hs
+++ b/Text/LaTeX/Packages/Graphicx.hs
@@ -1,5 +1,4 @@
-
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings, CPP #-}
 
 -- | This module allows you to use the LaTeX /graphicx/ library in order to
 --   insert graphics in a document and perform some transformations.
@@ -28,6 +27,9 @@
 import Text.LaTeX.Base.Types
 --
 import Data.Char (toLower)
+#if !MIN_VERSION_base(4,8,0)
+import Data.Functor ((<$>))
+#endif
 
 -- | The 'graphicx' package.
 --
@@ -63,11 +65,11 @@
 instance Render IGOption where
  render (IGWidth m) = "width=" <> render m
  render (IGHeight m) = "height=" <> render m
- render (KeepAspectRatio b) = "keepaspectratio=" <> fromString (fmap toLower $ show b)
+ render (KeepAspectRatio b) = "keepaspectratio=" <> fromString (toLower <$> show b)
  render (IGScale r) = "scale=" <> render r
  render (IGAngle a) = "angle=" <> render a
  render (IGTrim l b r t) = "trim=" <> renderChars ' ' [l,b,r,t]
- render (IGClip b) = "clip=" <> fromString (fmap toLower $ show b)
+ render (IGClip b) = "clip=" <> fromString (toLower <$> show b)
  render (IGPage p) = "page=" <> render p
 
 -- | Include an image in the document.
@@ -76,7 +78,7 @@
                 -> FilePath  -- ^ Image file
                 -> l
 includegraphics opts fp = fromLaTeX $ TeXComm "includegraphics"
- [ MOptArg $ fmap rendertex opts , FixArg $ TeXRaw $ fromString fp ]
+ [ MOptArg $ fmap rendertex opts, FixArg $ TeXRaw $ fromString fp ]
 
 -- | Rotate the content by the given angle in degrees.
 rotatebox :: LaTeXC l => Float -> l -> l
diff --git a/Text/LaTeX/Packages/Hyperref.hs b/Text/LaTeX/Packages/Hyperref.hs
--- a/Text/LaTeX/Packages/Hyperref.hs
+++ b/Text/LaTeX/Packages/Hyperref.hs
@@ -143,7 +143,7 @@
 
 -- | This package option sets the layout of PDF pages.
 pdfpagelayout :: LaTeXC l => PdfPageLayout -> l
-pdfpagelayout l = packageOption "pdfpagelayout" . raw . pack . show $ l
+pdfpagelayout = packageOption "pdfpagelayout" . raw . pack . show
 
 -- | Specification for how pages of a PDF should be displayed.
 data PdfPageLayout = SinglePage -- ^ Displays a single page; advancing flips the page.
diff --git a/Text/LaTeX/Packages/Multirow.hs b/Text/LaTeX/Packages/Multirow.hs
--- a/Text/LaTeX/Packages/Multirow.hs
+++ b/Text/LaTeX/Packages/Multirow.hs
@@ -10,7 +10,7 @@
  , multirow
  ) where
 
-import Data.Monoid ((<>))
+import qualified Data.Semigroup as SG ((<>))
 import Data.Maybe (catMaybes)
 import Text.LaTeX.Base.Syntax (LaTeX(TeXComm), TeXArg(FixArg, OptArg))
 import Text.LaTeX.Base.Class (LaTeXC, liftL)
@@ -35,9 +35,9 @@
 
 instance Render BigStrutsCount where
   render (BigStruts n)          = render n
-  render (BigStrutsTop n)       = "t" <> render n
-  render (BigStrutsBottom n)    = "b" <> render n
-  render (BigStrutsTopBottom n) = "tb" <> render n
+  render (BigStrutsTop n)       = "t" SG.<> render n
+  render (BigStrutsBottom n)    = "b" SG.<> render n
+  render (BigStrutsTopBottom n) = "tb" SG.<> render n
 
 -- | 'multirow' sets a piece of text in a tabular or similar
 -- environment, spanning multiple rows.
@@ -50,7 +50,7 @@
          -> Maybe Measure        -- ^ Optinal length used to raise or lower the text
          -> l                    -- ^ Actual text of the construct
          -> l
-multirow mVPos nrows mBigstruts width mVMove text =
+multirow mVPos nrows mBigstruts width mVMove =
   liftL (\l ->
            TeXComm "multirow" $ catMaybes  [ fmap (OptArg . rendertex) mVPos
                                            , Just (FixArg . rendertex $ nrows)
@@ -59,4 +59,4 @@
                                            , fmap (OptArg . rendertex) mVMove
                                            , Just (FixArg l)
                                            ]
-        ) text
+        )
diff --git a/Text/LaTeX/Packages/QRCode.hs b/Text/LaTeX/Packages/QRCode.hs
--- a/Text/LaTeX/Packages/QRCode.hs
+++ b/Text/LaTeX/Packages/QRCode.hs
@@ -76,4 +76,4 @@
                      | otherwise   = T.singleton c
 
 isSpecial :: Char -> Bool
-isSpecial c = elem c ("#$&^_~% \\{}" :: String)
+isSpecial c = c `elem` ("#$&^_~% \\{}" :: String)
diff --git a/Text/LaTeX/Packages/TikZ/PathBuilder.hs b/Text/LaTeX/Packages/TikZ/PathBuilder.hs
--- a/Text/LaTeX/Packages/TikZ/PathBuilder.hs
+++ b/Text/LaTeX/Packages/TikZ/PathBuilder.hs
@@ -44,11 +44,11 @@
 import Control.Applicative
 #endif
 
-data PathState = PS { currentPath :: TPath }
+newtype PathState = PS { currentPath :: TPath }
 
 -- | Use a /path builder/ to construct a value of type 'TPath'.
 --   Use 'bpath' for this purpose.
-data PathBuilder a = PB { pathBuilder :: State PathState a }
+newtype PathBuilder a = PB { pathBuilder :: State PathState a }
 
 -- Instances
 
@@ -73,16 +73,16 @@
 
 -- | Line from the current point to the given one.
 line :: TPoint -> PathBuilder ()
-line p = applyToPath $ (`Line`p)
+line p = applyToPath (`Line` p)
 
 -- | Rectangle with the current point as one cornder and the given point
 --   as the opposite corner.
 rectangle :: TPoint -> PathBuilder ()
-rectangle p = applyToPath $ (`Rectangle`p)
+rectangle p = applyToPath (`Rectangle` p)
 
 -- | Circle with the given radius centered at the current point.
 circle :: Double -> PathBuilder ()
-circle r = applyToPath $ (`Circle`r)
+circle r = applyToPath (`Circle` r)
 
 -- | Ellipse with width and height described by the arguments and centered
 --   at the current point.
diff --git a/Text/LaTeX/Packages/TikZ/Syntax.hs b/Text/LaTeX/Packages/TikZ/Syntax.hs
--- a/Text/LaTeX/Packages/TikZ/Syntax.hs
+++ b/Text/LaTeX/Packages/TikZ/Syntax.hs
@@ -151,7 +151,7 @@
                      -- point of @x@.
     deriving Show
 
-data GridOption =
+newtype GridOption =
    GridStep Step
    deriving Show
 
diff --git a/Text/LaTeX/Packages/Trees.hs b/Text/LaTeX/Packages/Trees.hs
--- a/Text/LaTeX/Packages/Trees.hs
+++ b/Text/LaTeX/Packages/Trees.hs
@@ -29,4 +29,4 @@
 
 instance Traversable Tree where
  sequenceA (Leaf fa) = Leaf <$> fa
- sequenceA (Node mfa ts) = liftA2 Node (sequenceA mfa) $ sequenceA $ fmap sequenceA ts
+ sequenceA (Node mfa ts) = liftA2 Node (sequenceA mfa) $ traverse sequenceA ts
