diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Releases
 
+## pandoc-utils 0.5.0 (2020-5-24)
+
+- Reorganize documentations and API.
+- Add new functions `convertFilter` and `convertFilterM` to convert between
+  filter functions.
+- Enable implicit conversion in `getConcatedFilter` and `getConcatedFilterM`.
+- Add a module exporting all the utility functions provided by the package.
+
 ## pandoc-utils 0.4.0 (2020-5-24)
 
 - Initial public release.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,11 +1,18 @@
 # pandoc-utils
 
+[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/Krasjet/pandoc-utils/build)](https://github.com/Krasjet/pandoc-utils/actions?query=workflow%3Abuild)
+[![Hackage](https://img.shields.io/hackage/v/pandoc-utils)](https://hackage.haskell.org/package/pandoc-utils)
+
 This package contains some useful functions for writing
 [Pandoc](https://pandoc.org/) filters and integrating Pandoc into Haskell
-applications such as [Hakyll](https://jaspervdj.be/hakyll/). It provides a
-composable wrapper for filters acting on nodes of the [Pandoc
-AST](https://hackage.haskell.org/package/pandoc-types/docs/Text-Pandoc-Definition.html).
+applications such as [Hakyll](https://jaspervdj.be/hakyll/).
 
+It provides a composable wrapper for filters acting on nodes of the [Pandoc
+AST](https://hackage.haskell.org/package/pandoc-types/docs/Text-Pandoc-Definition.html)
+and a few functions to convert between filters. The package also provides an
+attributes builder to work with attributes and some string utility functions to
+handle the switch from `String` to `Text` in pandoc-types 1.20.
+
 ## Filter conversion/composition
 
 As an example, let us look at the `behead` and `delink` filter from [Pandoc's
@@ -22,9 +29,9 @@
 
 Since `behead` has type `Block -> Block`, while `delink` has type `Inline ->
 [Inline]`, they are not naturally composable. However, this package provides a
-utility function `mkFilter` to convert them into a `PandocFilter`.
+utility function `mkFilter` to convert them into a wrapped `PandocFilter`.
 ```haskell
-import Text.Pandoc.Filter.Utils
+import Text.Pandoc.Utils
 
 beheadFilter :: PandocFilter
 beheadFilter = mkFilter behead
@@ -34,7 +41,7 @@
 ```
 `PandocFilter` is an alias for `PartialFilter Pandoc`, so you can also have
 `PartialFilter Inline`, etc. There is also a monadic version called
-`PartialFilterM` for encapsulating monadic filters.
+`PartialFilterM` for encapsulating monadic filter functions.
 
 The `PandocFilter` is a monoid so you can do something like,
 ```haskell
@@ -55,17 +62,27 @@
   let doc' = applyFilter myFilter doc
   writeHtml5String def doc'
 ```
-or get an unwrapped `Pandoc -> Pandoc` filter using `getFilter` (this function
-is also capable of doing implicit conversion from `PartialFilter a` to `b ->
-b`).
+or get an unwrapped `Pandoc -> Pandoc` filter function using `getFilter` (this
+function is also capable of doing implicit conversion from `PartialFilter a` to
+`b -> b`).
 ```haskell
 myPandocFilter :: Pandoc -> Pandoc
 myPandocFilter = getFilter myFilter
 ```
 
+If you just want to convert between Pandoc filter functions, e.g. `Inline ->
+[Inline]` to `Pandoc -> Pandoc` without using the wrapped filter, there is also
+`convertFilter` and `convertFilterM`
+```haskell
+delinkPandoc :: Pandoc -> Pandoc
+delinkPandoc = convertFilter delink
+```
+This function is slightly more powerful than `walk` and `walkM` in that it is
+also able to handle filter functions of type `a -> [a]` and `a -> m [a]`.
+
 For applying multiple filters, there is also a function called `applyFilters`,
-which takes a list of filters and apply it to a `Pandoc` document (or subnode)
-sequentially, from left to right.
+which takes a list of wrapped filters and apply it to a `Pandoc` document (or
+subnode) sequentially, from left to right.
 ```haskell
 myFilters :: [PandocFilter]
 myFilters =
@@ -87,7 +104,7 @@
 pandoc-utils also provides an attribute builder for handling attributes. You
 can create a new attributes by
 ```haskell
-ghci> import Text.Pandoc.Filter.Utils.AttrBuilder
+ghci> import Text.Pandoc.Utils
 ghci> import Text.Pandoc.Definition
 ghci> nullAttr `setId` "id" `addClass` "class" `addKVPair` ("key","value")
 ("id",["class"],[("key","value")])
diff --git a/pandoc-utils.cabal b/pandoc-utils.cabal
--- a/pandoc-utils.cabal
+++ b/pandoc-utils.cabal
@@ -2,16 +2,20 @@
 cabal-version:       2.0
 
 name:                pandoc-utils
-version:             0.4.0
+version:             0.5.0
 synopsis:
   Utility functions to work with Pandoc in Haskell applications.
 description:
   This package contains some useful functions for writing [Pandoc](https://pandoc.org/)
-  filters and integrating Pandoc into Haskell applications such
-  as [Hakyll](https://jaspervdj.be/hakyll/). It provides a
-  composable wrapper for filters acting on nodes of the [Pandoc
-  AST](https://hackage.haskell.org/package/pandoc-types/docs/Text-Pandoc-Definition.html).
+  filters and integrating Pandoc into Haskell applications such as
+  [Hakyll](https://jaspervdj.be/hakyll/) and web servers.
   .
+  It provides a composable wrapper for filters acting on nodes of the [Pandoc
+  AST](https://hackage.haskell.org/package/pandoc-types/docs/Text-Pandoc-Definition.html)
+  and a few functions to convert between filters. The package also provides an
+  attributes builder to work with attributes and some string utility functions
+  to handle the switch from 'String' to 'Text' in pandoc-types 1.20.
+  .
   For more examples, please see the [README](https://github.com/Krasjet/pandoc-utils) on GitHub.
 license:             MIT
 license-file:        LICENSE
@@ -35,6 +39,7 @@
   ghc-options:         -Wall
   exposed-modules:
       Text.Pandoc.Utils
+      Text.Pandoc.Utils.String
       Text.Pandoc.Filter.Utils
       Text.Pandoc.Filter.Utils.AttrBuilder
   build-depends:
diff --git a/src/Text/Pandoc/Filter/Utils.hs b/src/Text/Pandoc/Filter/Utils.hs
--- a/src/Text/Pandoc/Filter/Utils.hs
+++ b/src/Text/Pandoc/Filter/Utils.hs
@@ -5,25 +5,37 @@
 -- | This module contains some utility functions to work with different levels
 -- of Pandoc filters. For example, for the conversion from @'Inline' ->
 -- ['Inline']@ to @'Pandoc' -> 'Pandoc'@ filter.
+--
+-- If you don't need to compose filters and only want to convert between Pandoc
+-- filter functions, just use 'convertFilter' and 'convertFilterM'.
+--
+-- However, if you are working with multiple Pandoc filters of different type
+-- and want to compose them, this module also provides a monoid wrapper type
+-- 'PartialFilterM', which I call a "wrapped filter", and a few functions to
+-- apply, compose, and convert them.
 module Text.Pandoc.Filter.Utils (
-  -- * Definitions
-  PartialFilterM,
+  -- * Filter function conversion
+  convertFilter,
+  convertFilterM,
+  -- * Wrapped filter definitions
   PartialFilter,
-  PandocFilterM,
   PandocFilter,
-  -- * Filter application
-  applyFilterM,
+  PartialFilterM,
+  PandocFilterM,
+  -- * Filter function → Wrapped filter
+  ToPartialFilter (..),
+  mkConcatedFilter,
+  -- * Wrapped filter application/composition
   applyFilter,
-  -- * Filter composition
-  applyFiltersM,
   applyFilters,
-  -- * Filter conversion
-  getFilterM,
+  applyFilterM,
+  applyFiltersM,
+  -- * Wrapped filter → filter function
   getFilter,
-  getConcatedFilterM,
   getConcatedFilter,
-  ToPartialFilter (..),
-  mkConcatedFilter,
+  getFilterM,
+  getConcatedFilterM,
+  -- * Wrapped filter conversion
   toFilterM,
   ) where
 
@@ -35,7 +47,8 @@
 
 -- | @PartialFilterM m p@ is a wrapper for any monadic @p -> m p@ Pandoc
 -- filters acting on a subnode (e.g. 'Inline' or 'Block') of the 'Pandoc'
--- abstract syntax tree.
+-- abstract syntax tree. On this page, we will call it a "wrapped" filter to
+-- distinguish it from filter functions @a -> m b@.
 --
 -- * @m@: a monad.
 -- * @p@: the type of a subnode of 'Pandoc' (e.g. 'Inline').
@@ -47,7 +60,8 @@
 
 -- | @PartialFilter p@ is a wrapper for ordinary @p -> p@ Pandoc filters acting
 -- on a subnode (e.g. 'Inline' or 'Block') of the 'Pandoc' abstract syntax
--- tree.
+-- tree. On this page, we will call it a "wrapped" filter to distinguish it
+-- from filter functions @a -> b@.
 --
 -- * @p@: the type of a subnode of 'Pandoc' (e.g. 'Inline').
 type PartialFilter = PartialFilterM Identity
@@ -64,31 +78,39 @@
 -- * @m@: a monad.
 type PandocFilterM m = PartialFilterM m Pandoc
 
--- | Apply an ordinary filter to @p@, which returns @p@ directly.
+-- | Apply a wrapped filter to @p@, which returns @p@ directly.
 applyFilter
-  :: PartialFilter p -- ^ A wrapped partial filter.
+  :: PartialFilter p -- ^ A wrapped filter.
   -> p               -- ^ 'Pandoc' AST node.
   -> p               -- ^ Transformed node.
 applyFilter = (runIdentity .) . applyFilterM
 
--- | It is mostly the same as 'applyFilterM' and should be used when you don't
--- need to apply the filter immediately. The only difference is that it will
--- perform an implicit conversion if the requested filter function is of a
--- different type.
+-- | It is mostly the same as 'applyFilterM', which converts a wrapped monadic
+-- filter to a monadic filter function, but it should be used when you don't
+-- need to apply the filter immediately. There is a slight difference in that
+-- it will perform an implicit conversion if the requested filter function is
+-- of a different type.
+--
+-- For example, it can be used to convert a wrapped monadic filter
+-- @'PartialFilterM' 'IO' 'Inline'@ to monadic filter function @'Block' -> 'IO'
+-- 'Block'@.
 getFilterM
   :: (Monad m, Walkable a b)
-  => PartialFilterM m a -- ^ A wrapped partial filter on @a@.
-  -> (b -> m b)         -- ^ Unwrapped filter function that can be directly applied to @b@.
+  => PartialFilterM m a -- ^ A wrapped filter on @a@.
+  -> (b -> m b)         -- ^ Filter function that can be directly applied to @b@.
 getFilterM = applyFilterM . mkFilter
 
--- | It is mostly the same as 'applyFilter' and should be used when you don't
--- need to apply the filter immediately. The only difference is that it will
--- perform an implicit conversion if the requested filter function is of a
--- different type.
+-- | It is mostly the same as 'applyFilter', which converts a wrapped filter to
+-- a filter function, but it should be used when you don't need to apply the
+-- filter immediately. There is a slight difference in that it will perform an
+-- implicit conversion if the requested filter function is of a different type.
+--
+-- For example, it can be used to convert a wrapped filter @'PartialFilter'
+-- 'Inline'@ to filter function @'Block' -> 'Block'@.
 getFilter
   :: (Walkable a b)
   => PartialFilter a -- ^ A wrapped partial filter on @a@.
-  -> (b -> b)        -- ^ Unwrapped filter function that can be directly applied to @b@.
+  -> (b -> b)        -- ^ Filter function that can be directly applied to @b@.
 getFilter = applyFilter . mkFilter
 
 -- | The 'Semigroup' instance of `PartialFilterM`. @f1 <> f2@ will apply @f1@
@@ -103,11 +125,12 @@
 -- | A helper typeclass used as a polymorphic constructor of 'PartialFilterM'.
 class ToPartialFilter m f p where
   -- | The actual constructor of 'PartialFilterM'. It takes an ordinary filter
-  -- function @a -> b@ and wraps it as a 'PartialFilterM'. It can also be used
-  -- to convert between different types of @'PartialFilterM' m@.
+  -- function @a -> b@ and wraps it as a wrapped filter 'PartialFilterM'. It
+  -- can also be used to convert between different types of @'PartialFilterM'
+  -- m@.
   mkFilter
-    :: f                  -- ^ A partial filter function, usually @a -> a@ for some @'Walkable' a p@.
-    -> PartialFilterM m p -- ^ Wrapped partial Pandoc filter.
+    :: f                  -- ^ A filter function, usually @a -> a@ for some @'Walkable' a p@.
+    -> PartialFilterM m p -- ^ Wrapped Pandoc filter.
 
 instance (Monad m, Walkable a p) => ToPartialFilter m (a -> a) p where
   mkFilter = PartialFilterM . (return .) . walk
@@ -126,55 +149,92 @@
 instance (Monad m, Walkable a b) => ToPartialFilter m (PartialFilterM m a) b where
   mkFilter = mkFilter . applyFilterM
 
--- | Construct a 'PartialFilterM' from a list of filter functions of the same
--- type. The final filter is concatenated from left to right such that the
--- first element in the list will be applied first and the last element will be
--- applied at the end.
+-- | Construct a wrapped filter 'PartialFilterM' from a list of filter
+-- functions of the same type. The final filter is concatenated from left to
+-- right such that the first element in the list will be applied first and the
+-- last element will be applied at the end.
+--
+-- For example, it can be used to convert an list of filter functions
+-- @['Inline' -> ['Inline']]@ to a wrapped filter @'PandocFilter'@.
 mkConcatedFilter
   :: (Monad m, ToPartialFilter m f p, Foldable t)
   => t f                -- ^ A list of filter functions of the same type.
   -> PartialFilterM m p -- ^ Concatenated filter.
 mkConcatedFilter = foldMap mkFilter
 
--- | Convert an ordinary 'PartialFilter' to the monadic version
+-- | Convert an ordinary wrapped filter 'PartialFilter' to the monadic version
 -- 'PartialFilterM'.
+--
+-- For example, it can be used to convert an ordinary wrapped filter
+-- @'PartialFilter' 'Inline'@ to monadic wrapped filter @'PartialFilterM' 'IO'
+-- 'Inline'@.
 toFilterM
   :: (Monad m)
   => PartialFilter p    -- ^ An ordinary filter.
   -> PartialFilterM m p -- ^ The monadic version.
 toFilterM = PartialFilterM . (return .) . applyFilter
 
--- | Apply a list of monadic partial filters sequentially, from left to
--- right, i.e.  the first element in the list will be applied first and the
--- last element will be applied at the end.
+-- | Apply a list of monadic wrapped filters sequentially, from left to right,
+-- i.e. the first element in the list will be applied first and the last
+-- element will be applied at the end.
 applyFiltersM
   :: (Foldable t, Monad m)
-  => t (PartialFilterM m p) -- ^ A list of monadic partial filters.
+  => t (PartialFilterM m p) -- ^ A list of monadic wrapped filters.
   -> p                      -- ^ 'Pandoc' AST node.
   -> m p                    -- ^ Transformed node.
 applyFiltersM = applyFilterM . fold
 
--- | Apply a list of partial filters sequentially, from left to right, i.e.
+-- | Apply a list of wrapped filters sequentially, from left to right, i.e.
 -- the first element in the list will be applied first and the last element
 -- will be applied at the end.
 applyFilters
   :: (Foldable t)
-  => t (PartialFilter p) -- ^ A list of partial filter.
+  => t (PartialFilter p) -- ^ A list of wrapped filter.
   -> p                   -- ^ 'Pandoc' AST node.
   -> p                   -- ^ Transformed node.
 applyFilters = applyFilter . fold
 
--- | An alias for 'applyFiltersM', used when the filter is not used
--- immediately.
+-- | It is mostly the same as 'applyFiltersM', which converts a list of wrapped
+-- monadic filter to a monadic filter function, but it should be used when you
+-- don't need to apply the filter immediately. There is a slight difference in
+-- that it will perform an implicit conversion if the requested filter function
+-- is of a different type.
+--
+-- For example, it can be used to convert a list of wrapped monadic filter
+-- @['PartialFilterM' 'IO' 'Inline']@ to a filter function @'Block' -> 'IO'
+-- 'Block'@.
 getConcatedFilterM
-  :: (Foldable t, Monad m)
-  => t (PartialFilterM m p) -- ^ A list of monadic partial filters.
-  -> (p -> m p)             -- ^ Unwrapped monadic filter applicable to @p@ directly.
-getConcatedFilterM = applyFiltersM
+  :: (Foldable t, Monad m, Walkable a b)
+  => t (PartialFilterM m a) -- ^ A list of monadic partial filters on @a@.
+  -> (b -> m b)             -- ^ Monadic filter function applicable to @b@ directly.
+getConcatedFilterM = applyFilterM . mkConcatedFilter
 
--- | An alias for 'applyFilters', used when the filter is not used immediately.
+-- | It is mostly the same as 'applyFilters', which converts a list of wrapped
+-- filter to a filter function, but it should be used when you don't need to
+-- apply the filter immediately. There is a slight difference in that it will
+-- perform an implicit conversion if the requested filter function is of a
+-- different type.
+--
+-- For example, it can be used to convert a list of wrapped filter
+-- @['PartialFilter' 'Inline']@ to a filter function @'Block' -> 'Block'@.
 getConcatedFilter
-  :: (Foldable t)
-  => t (PartialFilter p) -- ^ A list of partial filter.
-  -> (p -> p)            -- ^ Unwrapped filter applicable to @p@ directly.
-getConcatedFilter = applyFilters
+  :: (Foldable t, Walkable a b)
+  => t (PartialFilter a) -- ^ A list of wrapped filter acting on @a@
+  -> (b -> b)            -- ^ Filter function applicable to @b@ directly.
+getConcatedFilter = applyFilter . mkConcatedFilter
+
+-- | Conversion between monadic filter functions, e.g. from @'Inline' ->
+-- 'IO' ['Inline']@ filter to @'Pandoc' -> 'IO' 'Pandoc'@ filter.
+convertFilterM
+  :: (Monad m, ToPartialFilter m f p)
+  => f                -- ^ A monadic filter function.
+  -> (p -> m p)       -- ^ Monadic filter function acting on @p@.
+convertFilterM = applyFilterM . mkFilter
+
+-- | Conversion between filter functions, e.g. from @'Inline' -> ['Inline']@
+-- filter to @'Pandoc' -> 'Pandoc'@ filter.
+convertFilter
+  :: (ToPartialFilter Identity f p)
+  => f        -- ^ A filter function.
+  -> (p -> p) -- ^ Filter function acting on @p@.
+convertFilter = applyFilter . mkFilter
diff --git a/src/Text/Pandoc/Filter/Utils/AttrBuilder.hs b/src/Text/Pandoc/Filter/Utils/AttrBuilder.hs
--- a/src/Text/Pandoc/Filter/Utils/AttrBuilder.hs
+++ b/src/Text/Pandoc/Filter/Utils/AttrBuilder.hs
@@ -9,7 +9,7 @@
   setId,
 ) where
 
-import Text.Pandoc.Utils
+import Text.Pandoc.Utils.String
 
 import Data.Bifunctor         (bimap, first, second)
 import Data.Text              (Text)
diff --git a/src/Text/Pandoc/Utils.hs b/src/Text/Pandoc/Utils.hs
--- a/src/Text/Pandoc/Utils.hs
+++ b/src/Text/Pandoc/Utils.hs
@@ -1,52 +1,13 @@
-{-# LANGUAGE TypeFamilies #-}
-
--- | Due to the switch from 'String' to 'Text' in pandoc-types 1.20, some
--- legacy filters might not work in newer versions. This module contains some
--- string conversion utility functions to make filters work in across different
--- versions.
+-- | This module exports all the utility functions provided by this package.
 module Text.Pandoc.Utils (
-  -- * Conversions
-  ToString (..),
-  ToText (..),
-  IsText (..),
-  -- * Reexport from Data.String
-  IsString (..),
-  ) where
-
-import qualified Data.Text as T
-
-import Data.String (IsString (..))
-import Data.Text   (Text)
-
--- | A helper typeclass for converting 'String' and 'Text' to 'String'.
-class IsString s => ToString s where
-  -- | Convert strings to 'String'.
-  toString :: s -> String
-
-instance Char ~ c => ToString [c] where
-  toString = id
-
-instance ToString Text where
-  toString = T.unpack
-
--- | A helper typeclass for converting 'String' and 'Text' to 'Text'.
-class IsString s => ToText s where
-  -- | Convert strings to 'Text'.
-  toText :: s -> Text
-
-instance Char ~ c => ToText [c] where
-  toText = T.pack
-
-instance ToText Text where
-  toText = id
-
--- | A helper typeclass for converting 'Text' to either 'String' or 'Text'.
-class IsText a where
-  -- | Convert from 'Text' to strings
-  fromText :: Text -> a
-
-instance Char ~ c => IsText [c] where
-  fromText = T.unpack
+  -- * Filter utils
+  module Text.Pandoc.Filter.Utils,
+  -- * Attribute builders
+  module Text.Pandoc.Filter.Utils.AttrBuilder,
+  -- * String conversions
+  module Text.Pandoc.Utils.String
+) where
 
-instance IsText Text where
-  fromText = id
+import Text.Pandoc.Filter.Utils
+import Text.Pandoc.Filter.Utils.AttrBuilder
+import Text.Pandoc.Utils.String
diff --git a/src/Text/Pandoc/Utils/String.hs b/src/Text/Pandoc/Utils/String.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Utils/String.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE TypeFamilies #-}
+
+-- | Due to the switch from 'String' to 'Text' in pandoc-types 1.20, some
+-- legacy filters might not work in newer versions. This module contains some
+-- string conversion utility functions to make filters work in across different
+-- versions.
+module Text.Pandoc.Utils.String (
+  -- * Conversions
+  ToString (..),
+  ToText (..),
+  IsText (..),
+  -- * Reexport from Data.String
+  IsString (..),
+  ) where
+
+import qualified Data.Text as T
+
+import Data.String (IsString (..))
+import Data.Text   (Text)
+
+-- | A helper typeclass for converting 'String' and 'Text' to 'String'.
+class IsString s => ToString s where
+  -- | Convert strings to 'String'.
+  toString :: s -> String
+
+instance Char ~ c => ToString [c] where
+  toString = id
+
+instance ToString Text where
+  toString = T.unpack
+
+-- | A helper typeclass for converting 'String' and 'Text' to 'Text'.
+class IsString s => ToText s where
+  -- | Convert strings to 'Text'.
+  toText :: s -> Text
+
+instance Char ~ c => ToText [c] where
+  toText = T.pack
+
+instance ToText Text where
+  toText = id
+
+-- | A helper typeclass for converting 'Text' to either 'String' or 'Text'.
+class IsText a where
+  -- | Convert from 'Text' to strings
+  fromText :: Text -> a
+
+instance Char ~ c => IsText [c] where
+  fromText = T.unpack
+
+instance IsText Text where
+  fromText = id
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -12,8 +12,7 @@
 import Test.Tasty
 import Test.Tasty.Hspec
 import Text.Pandoc.Definition
-import Text.Pandoc.Filter.Utils
-import Text.Pandoc.Filter.Utils.AttrBuilder
+import Text.Pandoc.Utils
 
 -- * Testing data
 
@@ -118,6 +117,9 @@
 beheadFilter :: PandocFilter
 beheadFilter = mkFilter behead
 
+beheadPandoc :: Pandoc -> Pandoc
+beheadPandoc = convertFilter behead
+
 delink :: Inline -> [Inline]
 delink (Link _ txt _) = txt
 delink x              = [x]
@@ -125,6 +127,9 @@
 delinkFilter :: PandocFilter
 delinkFilter = mkFilter delink
 
+delinkPandoc :: Pandoc -> Pandoc
+delinkPandoc = convertFilter delink
+
 myFilter :: PandocFilter
 myFilter = beheadFilter <> delinkFilter
 
@@ -238,6 +243,41 @@
       bl `shouldBe` expectedInlinePartial
       s' `shouldBe` T.pack "abcd"
 
+  describe "convertFilter" $ do
+    it "converts a -> a filter to Pandoc -> Pandoc filter" $ do
+      convertFilter capFilterInline docPara `shouldBe` expectedInline
+      convertFilter unParaFilterBlock docPara `shouldBe` expectedBlock
+
+    it "converts a -> a filter to b -> b partial filter" $
+      convertFilter capFilterInline blockPara `shouldBe` expectedInlinePartial
+
+    it "converts a -> [a] filter to Pandoc -> Pandoc filter" $ do
+      convertFilter dupFilterInline docPara `shouldBe` expectedInlineL
+      convertFilter dupFilterBlock docPara `shouldBe` expectedBlockL
+
+    it "converts a -> [a] filter to b -> b partial filter" $
+      convertFilter dupFilterInline blockPara `shouldBe` expectedInlinePartialL
+
+    it "converts a -> m a filter to Pandoc -> m Pandoc filter" $ do
+      let (doc, s) = runWriter $ convertFilterM extractFilterInlineM docPara
+      doc `shouldBe` expectedInline
+      s `shouldBe` T.pack "abcd"
+
+    it "converts a -> m a filter to b -> m b filter" $ do
+      let (bl, s) = runWriter $ convertFilterM extractFilterInlineM blockPara
+      bl `shouldBe` expectedInlinePartial
+      s `shouldBe` T.pack "abcd"
+
+    it "converts a -> m [a] filter to Pandoc -> m Pandoc filter" $ do
+      let (doc, s) = runWriter $ convertFilterM extractFilterInlineML docPara
+      doc `shouldBe` expectedInlineL
+      s `shouldBe` T.pack "abcd"
+
+    it "converts a -> m [a] filter to b -> m b filter" $ do
+      let (bl, s) = runWriter $ convertFilterM extractFilterInlineML blockPara
+      bl `shouldBe` expectedInlinePartialL
+      s `shouldBe` T.pack "abcd"
+
   describe "getFilter" $ do
     it "converts PartialFilter a to a -> a" $ do
       let fInline = mkFilter capFilterInline :: PartialFilter Inline
@@ -294,12 +334,10 @@
     it "applys merge correctly" $
       applyFilter merge compPara2 `shouldBe` expectedMerge
 
-  describe "applyFilters and monoid" $ do
+  describe "applyFilters" $ do
     it "applys PartialFilter composition from left to right" $ do
       applyFilter (dup <> merge) compPara `shouldBe` expectedDupMerge
       applyFilter (merge <> dup) compPara `shouldBe` expectedMergeDup
-      applyFilters [dup, merge] compPara `shouldBe` expectedDupMerge
-      applyFilters [merge, dup] compPara `shouldBe` expectedMergeDup
 
     it "applys PartialFilterM composition from left to right" $ do
       let (doc, s) = runWriter $ applyFilterM (extract <> toFilterM dup) compPara
@@ -310,12 +348,58 @@
       doc' `shouldBe` expectedDup
       s' `shouldBe` T.pack "abcdabcd"
 
+  describe "monoid instance" $ do
+    it "applys PartialFilter composition from left to right" $ do
+      applyFilters [dup, merge] compPara `shouldBe` expectedDupMerge
+      applyFilters [merge, dup] compPara `shouldBe` expectedMergeDup
+
+    it "applys PartialFilterM composition from left to right" $ do
+      let (doc, s) = runWriter $ applyFiltersM [extract, toFilterM dup] compPara
+      doc `shouldBe` expectedDup
+      s `shouldBe` T.pack "abcd"
+
+      let (doc', s') = runWriter $ applyFiltersM [toFilterM dup, extract] compPara
+      doc' `shouldBe` expectedDup
+      s' `shouldBe` T.pack "abcdabcd"
+
+  let dupInl = mkFilter dupFilterInline     :: PartialFilter [Inline]
+      mergeInl = mkFilter mergeFilterInline :: PartialFilter [Inline]
+      extractInl = mkFilter extractFilter   :: PartialFilterM (Writer Text) [Inline]
+
+  describe "getConcatedFilter" $ do
+    it "converts [PartialFilter a] to a -> a, applied from left to right" $ do
+      getConcatedFilter [dupInl, mergeInl] [Str "abcd"] `shouldBe` [Str "abcdabcd"]
+      getConcatedFilter [mergeInl, dupInl] [Str "abcd"] `shouldBe` [Str "abcd", Str "abcd"]
+
+    it "converts [PartialFilterM m a] to a -> m a, applied from left to right" $ do
+      let (doc, s) = runWriter $ getConcatedFilterM [extractInl, toFilterM dupInl] [Str "abcd"]
+      doc `shouldBe` [Str "abcd", Str "abcd"]
+      s `shouldBe` T.pack "abcd"
+
+      let (doc', s') = runWriter $ getConcatedFilterM [toFilterM dupInl, extractInl] [Str "abcd"]
+      doc' `shouldBe` [Str "abcd", Str "abcd"]
+      s' `shouldBe` T.pack "abcdabcd"
+
+    it "converts [PartialFilter a] to b -> b, applied from left to right" $ do
+      getConcatedFilter [dupInl, mergeInl] compPara `shouldBe` expectedDupMerge
+      getConcatedFilter [mergeInl, dupInl] compPara `shouldBe` expectedMergeDup
+
+    it "converts [PartialFilterM m a] to b -> m b, applied from left to right" $ do
+      let (doc, s) = runWriter $ getConcatedFilterM [extractInl, toFilterM dupInl] compPara
+      doc `shouldBe` expectedDup
+      s `shouldBe` T.pack "abcd"
+
+      let (doc', s') = runWriter $ getConcatedFilterM [toFilterM dupInl, extractInl] compPara
+      doc' `shouldBe` expectedDup
+      s' `shouldBe` T.pack "abcdabcd"
+
 readmeSpec :: Spec
 readmeSpec = parallel $
   describe "readme example" $ do
     it "processes filter examples correctly on AST level" $ do
       applyFilters [beheadFilter, delinkFilter] readmeDoc `shouldBe` expectedDoc
       applyFilter myFilter readmeDoc `shouldBe` expectedDoc
+      (delinkPandoc . beheadPandoc) readmeDoc `shouldBe` expectedDoc
 
     it "processes filter examples correctly on Text level" $ do
       fromRight "" (mdToHtml readmeText) `shouldBe` expectedHtml
