diff --git a/shikensu.cabal b/shikensu.cabal
--- a/shikensu.cabal
+++ b/shikensu.cabal
@@ -1,5 +1,5 @@
 name: shikensu
-version: 0.1.3
+version: 0.2.0
 category: File IO
 
 synopsis:
@@ -40,6 +40,7 @@
     Shikensu,
     Shikensu.Contrib,
     Shikensu.Contrib.IO,
+    Shikensu.Internal.Utilities,
     Shikensu.Metadata,
     Shikensu.Sorting,
     Shikensu.Types,
@@ -53,13 +54,17 @@
     filepath == 1.4.*,
     flow == 1.0.*,
     Glob == 0.7.*,
-    unordered-containers == 0.2.*
+    unordered-containers == 0.2.*,
+    text >= 1.2 && < 2
 
 
 test-suite tests
   default-language:
     Haskell2010
 
+  default-extensions:
+    OverloadedStrings
+
   ghc-options:
     -Wall -threaded -rtsopts -with-rtsopts=-N
 
@@ -76,7 +81,8 @@
     Test.Contrib,
     Test.Example,
     Test.Helpers,
-    Test.Shikensu
+    Test.Shikensu,
+    Test.Utilities
 
   build-depends:
     aeson,
@@ -88,5 +94,5 @@
     shikensu,
     tasty == 0.11.*,
     tasty-hunit == 0.9.*,
-    text >= 1.2 && < 2,
+    text,
     unordered-containers
diff --git a/src/Shikensu.hs b/src/Shikensu.hs
--- a/src/Shikensu.hs
+++ b/src/Shikensu.hs
@@ -4,16 +4,17 @@
 
 -}
 module Shikensu
-  ( list
+    ( list
+    , listF
 
-  , forkDefinition
-  , makeDefinition
-  , makeDictionary
-  ) where
+    , forkDefinition
+    , makeDefinition
+    , makeDictionary
+    ) where
 
 import Flow
+import Shikensu.Internal.Utilities
 import Shikensu.Types
-import Shikensu.Utilities
 import System.FilePath
 
 import qualified Data.HashMap.Strict as HashMap (empty)
@@ -24,7 +25,7 @@
 -- IO
 
 
-{-| Make a single dictionary based on multiple glob patterns and a path to a directory.
+{-| Make a single dictionary based on a path to a directory and multiple glob patterns.
 
 1. Compile patterns so `globDir` can use them.
 2. Run `globDir` function on the given (root) path.
@@ -34,18 +35,23 @@
 5. Merge the dictionaries into one dictionary.
 
 -}
-list :: [Pattern] -> FilePath -> IO Dictionary
-list patterns rootDir =
-  patterns
-    |> compilePatterns
-    |> globDir rootDir
-    |> fmap (List.zip patterns)
-    |> fmap (List.map (uncurry . makeDictionary $ rootDir))
-    |> fmap (List.concat)
+list :: FilePath -> [Pattern] -> IO Dictionary
+list rootDir patterns =
+    patterns
+        |> compilePatterns
+        |> globDir rootDir
+        |> fmap (List.zip patterns)
+        |> fmap (List.map (uncurry . makeDictionary $ rootDir))
+        |> fmap (List.concat)
 
 
+listF :: [Pattern] -> FilePath -> IO Dictionary
+listF patterns rootDir =
+    list rootDir patterns
 
 
+
+
 -- PURE
 
 
@@ -53,20 +59,20 @@
 -}
 forkDefinition :: FilePath -> Definition -> Definition
 forkDefinition newLocalPath def =
-  Definition
-    { basename        = takeBaseName newLocalPath
-    , dirname         = takeDirName newLocalPath
-    , extname         = takeExtension newLocalPath
-    , pattern         = (pattern def)
-    , rootDirname     = (rootDirname def)
-    , workingDirname  = (workingDirname def)
+    Definition
+        { basename        = takeBaseName newLocalPath
+        , dirname         = takeDirName newLocalPath
+        , extname         = takeExtension newLocalPath
+        , pattern         = (pattern def)
+        , rootDirname     = (rootDirname def)
+        , workingDirname  = (workingDirname def)
 
-    -- Additional properties
-    , content         = (content def)
-    , metadata        = (metadata def)
-    , parentPath      = compileParentPath $ takeDirName newLocalPath
-    , pathToRoot      = compilePathToRoot $ takeDirName newLocalPath
-    }
+        -- Additional properties
+        , content         = (content def)
+        , metadata        = (metadata def)
+        , parentPath      = compileParentPath $ takeDirName newLocalPath
+        , pathToRoot      = compilePathToRoot $ takeDirName newLocalPath
+        }
 
 
 
@@ -79,44 +85,45 @@
 - the workspace path `example/test/hello.md`
 
 > Definition
->   { basename = "hello"
->   , dirname = "test"
->   , extname = ".md"
->   , pattern = "example/**/*.md"
->   , rootDirname = "/Users/icidasset/Projects/shikensu"
->   , workingDirname = "example"
+>     { basename = "hello"
+>     , dirname = "test"
+>     , extname = ".md"
+>     , pattern = "example/**/*.md"
+>     , rootDirname = "/Users/icidasset/Projects/shikensu"
+>     , workingDirname = "example"
 >
->   , content = Nothing
->   , metadata = HashMap.empty
->   , parentPath = "../"
->   , pathToRoot = "../../"
->   }
+>     , content = Nothing
+>     , metadata = HashMap.empty
+>     , parentPath = "../"
+>     , pathToRoot = "../../"
+>     }
 
 -}
 makeDefinition :: FilePath -> Pattern -> FilePath -> Definition
 makeDefinition _rootDirname _pattern _workspacePath =
-  let
-    workingDir  = cleanPath . (commonDirectory) $ _pattern
-    localPath   = cleanPath . (stripPrefix workingDir) . cleanPath $ _workspacePath
-  in
-    Definition
-      { basename        = takeBaseName localPath
-      , dirname         = takeDirName localPath
-      , extname         = takeExtension localPath
-      , pattern         = _pattern
-      , rootDirname     = dropTrailingPathSeparator _rootDirname
-      , workingDirname  = workingDir
+    let
+        workingDir  = cleanPath . (commonDirectory) $ _pattern
+        localPath   = cleanPath . (stripPrefix workingDir) . cleanPath $ _workspacePath
+    in
+        Definition
+            { basename        = takeBaseName localPath
+            , dirname         = takeDirName localPath
+            , extname         = takeExtension localPath
+            , pattern         = _pattern
+            , rootDirname     = dropTrailingPathSeparator _rootDirname
+            , workingDirname  = workingDir
 
-      -- Additional properties
-      , content         = Nothing
-      , metadata        = HashMap.empty
-      , parentPath      = compileParentPath $ takeDirName localPath
-      , pathToRoot      = compilePathToRoot $ takeDirName localPath
-      }
+            -- Additional properties
+            , content         = Nothing
+            , metadata        = HashMap.empty
+            , parentPath      = compileParentPath $ takeDirName localPath
+            , pathToRoot      = compilePathToRoot $ takeDirName localPath
+            }
 
 
 
 {-| Make a Dictionary.
 -}
 makeDictionary :: FilePath -> Pattern -> [FilePath] -> Dictionary
-makeDictionary _rootDirname _pattern = List.map (makeDefinition _rootDirname _pattern)
+makeDictionary _rootDirname _pattern =
+    List.map (makeDefinition _rootDirname _pattern)
diff --git a/src/Shikensu/Contrib.hs b/src/Shikensu/Contrib.hs
--- a/src/Shikensu/Contrib.hs
+++ b/src/Shikensu/Contrib.hs
@@ -2,34 +2,34 @@
 
 -}
 module Shikensu.Contrib
-  ( clearMetadata
-  , clearMetadataDef
-  , clone
-  , copyPropsToMetadata
-  , copyPropsToMetadataDef
-  , exclude
-  , insertMetadata
-  , insertMetadataDef
-  , permalink
-  , permalinkDef
-  , prefixDirname
-  , prefixDirnameDef
-  , rename
-  , renameDef
-  , renameExt
-  , renameExtDef
-  , renderContent
-  , renderContentDef
-  , replaceMetadata
-  , replaceMetadataDef
-  ) where
+    ( clearMetadata
+    , clearMetadataDef
+    , clone
+    , copyPropsToMetadata
+    , copyPropsToMetadataDef
+    , exclude
+    , insertMetadata
+    , insertMetadataDef
+    , permalink
+    , permalinkDef
+    , prefixDirname
+    , prefixDirnameDef
+    , rename
+    , renameDef
+    , renameExt
+    , renameExtDef
+    , renderContent
+    , renderContentDef
+    , replaceMetadata
+    , replaceMetadataDef
+    ) where
 
 import Data.ByteString (ByteString)
 import Flow
 import Shikensu (forkDefinition)
+import Shikensu.Internal.Utilities (cleanPath, compileParentPath, compilePathToRoot)
 import Shikensu.Metadata (transposeToMetadata)
 import Shikensu.Types
-import Shikensu.Utilities (cleanPath, compileParentPath, compilePathToRoot)
 import System.FilePath (FilePath, combine)
 
 import qualified Data.HashMap.Strict as HashMap (empty, union)
@@ -40,11 +40,13 @@
 Replace the current hash map with an empty one.
 -}
 clearMetadata :: Dictionary -> Dictionary
-clearMetadata = fmap (clearMetadataDef)
+clearMetadata =
+    fmap (clearMetadataDef)
 
 
 clearMetadataDef :: Definition -> Definition
-clearMetadataDef def = def { metadata = HashMap.empty }
+clearMetadataDef def =
+    def { metadata = HashMap.empty }
 
 
 
@@ -58,13 +60,13 @@
 -}
 clone :: FilePath -> FilePath -> Dictionary -> Dictionary
 clone existingPath newPath dict =
-  let
-    makeNew = \def acc ->
-      if (localPath def) == existingPath
-        then acc ++ [forkDefinition newPath def]
-        else acc
-  in
-    dict ++ (foldr makeNew [] dict)
+    let
+        makeNew = \def acc ->
+            if (localPath def) == existingPath
+                then acc ++ [forkDefinition newPath def]
+                else acc
+    in
+        dict ++ (foldr makeNew [] dict)
 
 
 
@@ -74,13 +76,14 @@
 to see what properties get put in here.
 -}
 copyPropsToMetadata :: Dictionary -> Dictionary
-copyPropsToMetadata = fmap (copyPropsToMetadataDef)
+copyPropsToMetadata =
+    fmap (copyPropsToMetadataDef)
 
 
 copyPropsToMetadataDef :: Definition -> Definition
-copyPropsToMetadataDef def = def {
-    metadata = HashMap.union (transposeToMetadata def) (metadata def)
-  }
+copyPropsToMetadataDef def =
+    def
+        { metadata = HashMap.union (transposeToMetadata def) (metadata def) }
 
 
 
@@ -89,7 +92,8 @@
 Filter out the definitions that have the given `localPath`.
 -}
 exclude :: FilePath -> Dictionary -> Dictionary
-exclude path = filter (\def -> (localPath def) /= path)
+exclude path =
+    filter (\def -> (localPath def) /= path)
 
 
 
@@ -98,11 +102,13 @@
 Merge the current hash map with another one.
 -}
 insertMetadata :: Metadata -> Dictionary -> Dictionary
-insertMetadata a = fmap (insertMetadataDef a)
+insertMetadata a =
+    fmap (insertMetadataDef a)
 
 
 insertMetadataDef :: Metadata -> Definition -> Definition
-insertMetadataDef given def = def { metadata = HashMap.union given (metadata def) }
+insertMetadataDef given def =
+    def { metadata = HashMap.union given (metadata def) }
 
 
 
@@ -115,26 +121,24 @@
 > permalink "index" dictionary
 -}
 permalink :: String -> Dictionary -> Dictionary
-permalink a = fmap (permalinkDef a)
+permalink a =
+    fmap (permalinkDef a)
 
 
 permalinkDef :: String -> Definition -> Definition
 permalinkDef newBasename def =
-  if (basename def) /= newBasename
-    then
-      let
-        newDirname = cleanPath $ combine (dirname def) (basename def)
-      in
-        def {
-          basename    = newBasename
-        , dirname     = newDirname
-
-        , parentPath  = compileParentPath $ newDirname
-        , pathToRoot  = compilePathToRoot $ newDirname
-        }
-
+    if (basename def) /= newBasename then
+        let
+            newDirname = cleanPath $ combine (dirname def) (basename def)
+        in
+            def
+                { basename    = newBasename
+                , dirname     = newDirname
+                , parentPath  = compileParentPath $ newDirname
+                , pathToRoot  = compilePathToRoot $ newDirname
+                }
     else
-      def
+        def
 
 
 
@@ -148,15 +152,14 @@
 
 prefixDirnameDef :: String -> Definition -> Definition
 prefixDirnameDef prefix def =
-  let
-    newDirname = prefix ++ (dirname def)
-  in
-    def {
-      dirname     = newDirname
-
-    , parentPath  = compileParentPath $ newDirname
-    , pathToRoot  = compilePathToRoot $ newDirname
-    }
+    let
+        newDirname = prefix ++ (dirname def)
+    in
+        def
+            { dirname     = newDirname
+            , parentPath  = compileParentPath $ newDirname
+            , pathToRoot  = compilePathToRoot $ newDirname
+            }
 
 
 
@@ -190,14 +193,15 @@
 > -- now have the extname ".html"
 -}
 renameExt :: String -> String -> Dictionary -> Dictionary
-renameExt a b = fmap (renameExtDef a b)
+renameExt a b =
+    fmap (renameExtDef a b)
 
 
 renameExtDef :: String -> String -> Definition -> Definition
 renameExtDef oldExtname newExtname def =
-  if (extname def) == oldExtname
-    then def { extname = newExtname }
-    else def
+    if (extname def) == oldExtname
+        then def { extname = newExtname }
+        else def
 
 
 
@@ -209,11 +213,13 @@
 You can use this to render templates, markdown, etc.
 -}
 renderContent :: (Definition -> Maybe ByteString) -> Dictionary -> Dictionary
-renderContent a = fmap (renderContentDef a)
+renderContent a =
+    fmap (renderContentDef a)
 
 
 renderContentDef :: (Definition -> Maybe ByteString) -> Definition -> Definition
-renderContentDef renderer def = def { content = renderer def }
+renderContentDef renderer def =
+    def { content = renderer def }
 
 
 
@@ -222,8 +228,10 @@
 Replace the current hash map with another one.
 -}
 replaceMetadata :: Metadata -> Dictionary -> Dictionary
-replaceMetadata a = fmap (replaceMetadataDef a)
+replaceMetadata a =
+    fmap (replaceMetadataDef a)
 
 
 replaceMetadataDef :: Metadata -> Definition -> Definition
-replaceMetadataDef given def = def { metadata = given }
+replaceMetadataDef given def =
+    def { metadata = given }
diff --git a/src/Shikensu/Contrib/IO.hs b/src/Shikensu/Contrib/IO.hs
--- a/src/Shikensu/Contrib/IO.hs
+++ b/src/Shikensu/Contrib/IO.hs
@@ -2,11 +2,11 @@
 
 -}
 module Shikensu.Contrib.IO
-  ( Shikensu.Contrib.IO.read
-  , Shikensu.Contrib.IO.readDef
-  , Shikensu.Contrib.IO.write
-  , Shikensu.Contrib.IO.writeDef
-  ) where
+    ( Shikensu.Contrib.IO.read
+    , Shikensu.Contrib.IO.readDef
+    , Shikensu.Contrib.IO.write
+    , Shikensu.Contrib.IO.writeDef
+    ) where
 
 import Data.Maybe (fromMaybe)
 import Flow
@@ -24,22 +24,23 @@
 put that content in the `content` property.
 -}
 read :: Dictionary -> IO Dictionary
-read = Utilities.mapIO (readDef)
+read =
+    Utilities.mapIO (readDef)
 
 
 readDef :: Definition -> IO Definition
 readDef def =
-  let
-    absPath = absolutePath def
-  in
-    doesFileExist absPath >>= \exists ->
-      if exists then
-        fmap
-          (\c -> def { content = Just c })
-          (B.readFile absPath)
-      else
-        return
-          def { content = Nothing }
+    let
+        absPath = absolutePath def
+    in
+        doesFileExist absPath >>= \exists ->
+            if exists then
+                fmap
+                    (\c -> def { content = Just c })
+                    (B.readFile absPath)
+            else
+                return
+                    def { content = Nothing }
 
 
 
@@ -49,15 +50,16 @@
 The path of the new file is `joinPath [rootDirname, givenDirectoryName, localPath]`.
 -}
 write :: FilePath -> Dictionary -> IO Dictionary
-write dest = Utilities.mapIO (writeDef dest)
+write dest =
+    Utilities.mapIO (writeDef dest)
 
 
 writeDef :: FilePath -> Definition -> IO Definition
 writeDef dest def =
-  let
-    path = joinPath [rootDirname def, dest, localPath def]
-    cont = fromMaybe B.empty (content def)
-  in
-    createDirectoryIfMissing True (takeDirectory path)
-      >> B.writeFile path cont
-      >> return def
+    let
+        path = joinPath [rootDirname def, dest, localPath def]
+        cont = fromMaybe B.empty (content def)
+    in
+        createDirectoryIfMissing True (takeDirectory path)
+            >> B.writeFile path cont
+            >> return def
diff --git a/src/Shikensu/Internal/Utilities.hs b/src/Shikensu/Internal/Utilities.hs
new file mode 100644
--- /dev/null
+++ b/src/Shikensu/Internal/Utilities.hs
@@ -0,0 +1,113 @@
+{-| Internal utility functions.
+
+-}
+module Shikensu.Internal.Utilities
+    ( cleanPath
+    , commonDirectory
+    , compilePatterns
+    , compileParentPath
+    , compilePathToRoot
+    , globDir
+    , replaceSingleDot
+    , stripPrefix
+    , takeDirName
+    ) where
+
+import Data.Maybe (fromMaybe)
+import Flow
+import Shikensu.Types (Pattern)
+import System.FilePath
+
+import qualified Data.List as List (map, stripPrefix)
+import qualified System.FilePath.Glob as Glob
+
+
+{-| "Clean up" a path.
+
+> `/directory/./nested/` -> `directory/nested`
+> `./` -> ``
+> `.` -> ``
+
+-}
+cleanPath :: FilePath -> FilePath
+cleanPath =
+    normalise .> dropTrailingPathSeparator .> dropDrive .> replaceSingleDot
+
+
+{-| Get the common directory from a Pattern.
+-}
+commonDirectory :: Pattern -> FilePath
+commonDirectory pattern =
+    (Glob.compile .> Glob.commonDirectory .> fst) pattern
+
+
+{-| Compile a list of `Pattern`s to `Glob.Pattern`s.
+-}
+compilePatterns :: [Pattern] -> [Glob.Pattern]
+compilePatterns =
+    List.map Glob.compile
+
+
+{-| Path to parent, when there is one.
+
+> Just "../" or Nothing
+
+-}
+compileParentPath :: FilePath -> Maybe FilePath
+compileParentPath dirname =
+    case dirname of
+        "" -> Nothing
+        _  -> Just "../"
+
+
+{-| Path to root.
+
+Example, if `dirname` is 'example/subdir',
+then this will be `../../`.
+
+If the `dirname` is empty,
+then this will be empty as well.
+
+-}
+compilePathToRoot :: FilePath -> FilePath
+compilePathToRoot dirname =
+    if dirname == "" then
+        ""
+    else
+        dirname
+            |> splitDirectories
+            |> fmap (\_ -> "..")
+            |> joinPath
+            |> addTrailingPathSeparator
+
+
+{-| List contents of a directory using a glob pattern.
+Returns a relative path, based on the given rootDirname.
+-}
+globDir :: FilePath -> [Glob.Pattern] -> IO [[FilePath]]
+globDir rootDir patterns =
+    Glob.globDir patterns rootDir
+        |> fmap (fst)
+        |> fmap (List.map . List.map . makeRelative $ rootDir)
+
+
+{-| If the path is a single dot, return an empty string.
+Otherwise return the path.
+-}
+replaceSingleDot :: String -> String
+replaceSingleDot path =
+    if path == "." then "" else path
+
+
+{-| Strip prefix.
+-}
+stripPrefix :: String -> String -> String
+stripPrefix prefix target =
+    fromMaybe target (List.stripPrefix prefix target)
+
+
+{-| Take dirname and replace single dot.
+-}
+takeDirName :: FilePath -> FilePath
+takeDirName =
+    replaceSingleDot . takeDirectory
diff --git a/src/Shikensu/Metadata.hs b/src/Shikensu/Metadata.hs
--- a/src/Shikensu/Metadata.hs
+++ b/src/Shikensu/Metadata.hs
@@ -2,9 +2,9 @@
 
 -}
 module Shikensu.Metadata
-  ( transposeMetadata
-  , transposeToMetadata
-  ) where
+    ( transposeMetadata
+    , transposeToMetadata
+    ) where
 
 import Flow
 import Shikensu.Types
@@ -20,35 +20,35 @@
 which implements the Aeson.FromJSON instance.
 
 > data Example =
->   Example { some :: Text }
->   deriving (Generic, FromJSON)
+>     Example { some :: Text }
+>     deriving (Generic, FromJSON)
 >
 > hashMap     = HashMap.fromList [ ("some", "metadata") ]
 > defaultEx   = Example { some = "default" }
-> example     = transposeMetadata hashMap defaultExample :: Example
+> example     = transposeMetadata hashMap defaultEx :: Example
 
 -}
 transposeMetadata :: Aeson.FromJSON a => Metadata -> a -> a
 transposeMetadata hashMap fallback =
-  let
-    result = hashMap
-      |> Aeson.toJSON
-      |> Aeson.fromJSON :: Aeson.FromJSON b => Aeson.Result b
-  in
-    case result of
-      Aeson.Success x -> x
-      Aeson.Error _   -> fallback
+    let
+        result = hashMap
+            |> Aeson.toJSON
+            |> Aeson.fromJSON :: Aeson.FromJSON b => Aeson.Result b
+    in
+        case result of
+            Aeson.Success x -> x
+            Aeson.Error _   -> fallback
 
 
 {-| Inverse of `transposeMetadata`.
 -}
 transposeToMetadata :: (Aeson.ToJSON a) => a -> Metadata
 transposeToMetadata generic =
-  let
-    result = generic
-      |> Aeson.toJSON
-      |> Aeson.fromJSON :: Aeson.FromJSON b => Aeson.Result b
-  in
-    case result of
-      Aeson.Success x -> x
-      Aeson.Error _   -> HashMap.empty
+    let
+        result = generic
+            |> Aeson.toJSON
+            |> Aeson.fromJSON :: Aeson.FromJSON b => Aeson.Result b
+    in
+        case result of
+            Aeson.Success x -> x
+            Aeson.Error _   -> HashMap.empty
diff --git a/src/Shikensu/Sorting.hs b/src/Shikensu/Sorting.hs
--- a/src/Shikensu/Sorting.hs
+++ b/src/Shikensu/Sorting.hs
@@ -2,8 +2,8 @@
 
 -}
 module Shikensu.Sorting
-  ( sortByAbsolutePath
-  ) where
+    ( sortByAbsolutePath
+    ) where
 
 import Shikensu.Types (Definition, absolutePath)
 
@@ -15,4 +15,4 @@
 -}
 sortByAbsolutePath :: Definition -> Definition -> Ordering
 sortByAbsolutePath defA defB =
-  compare (absolutePath defA) (absolutePath defB)
+    compare (absolutePath defA) (absolutePath defB)
diff --git a/src/Shikensu/Types.hs b/src/Shikensu/Types.hs
--- a/src/Shikensu/Types.hs
+++ b/src/Shikensu/Types.hs
@@ -11,33 +11,33 @@
 {-| A file definition, along with some additional properties.
 -}
 data Definition =
-  Definition
-    { basename :: String
-    , dirname :: FilePath
-    , extname :: String
-    , pattern :: Pattern
-    , rootDirname :: FilePath
-    , workingDirname :: FilePath
+    Definition
+        { basename :: String
+        , dirname :: FilePath
+        , extname :: String
+        , pattern :: Pattern
+        , rootDirname :: FilePath
+        , workingDirname :: FilePath
 
-    -- Additional properties
-    , content :: Maybe ByteString
-    , metadata :: Metadata
-    , parentPath :: Maybe FilePath
-    , pathToRoot :: FilePath
-    } deriving (Eq, Show)
+        -- Additional properties
+        , content :: Maybe ByteString
+        , metadata :: Metadata
+        , parentPath :: Maybe FilePath
+        , pathToRoot :: FilePath
+        } deriving (Eq, Show)
 
 
 instance ToJSON Definition where
-  toJSON def =
-    object
-      [ "basename"        .= basename def
-      , "dirname"         .= dirname def
-      , "extname"         .= extname def
-      , "pattern"         .= pattern def
-      , "workingDirname"  .= workingDirname def
-      , "parentPath"      .= parentPath def
-      , "pathToRoot"      .= pathToRoot def
-      ]
+    toJSON def =
+        object
+            [ "basename"        .= basename def
+            , "dirname"         .= dirname def
+            , "extname"         .= extname def
+            , "pattern"         .= pattern def
+            , "workingDirname"  .= workingDirname def
+            , "parentPath"      .= parentPath def
+            , "pathToRoot"      .= pathToRoot def
+            ]
 
 
 
@@ -57,14 +57,14 @@
 
 absolutePath :: Definition -> String
 absolutePath def =
-  joinPath [rootDirname def, workspacePath def]
+    joinPath [rootDirname def, workspacePath def]
 
 
 localPath :: Definition -> String
 localPath def =
-  joinPath [dirname def, (basename def) ++ (extname def)]
+    joinPath [dirname def, (basename def) ++ (extname def)]
 
 
 workspacePath :: Definition -> String
 workspacePath def =
-  joinPath [workingDirname def, localPath def]
+    joinPath [workingDirname def, localPath def]
diff --git a/src/Shikensu/Utilities.hs b/src/Shikensu/Utilities.hs
--- a/src/Shikensu/Utilities.hs
+++ b/src/Shikensu/Utilities.hs
@@ -1,120 +1,104 @@
-{-| Utilities, mainly for internal use.
-
--}
 module Shikensu.Utilities
-  ( cleanPath
-  , commonDirectory
-  , compilePatterns
-  , compileParentPath
-  , compilePathToRoot
-  , globDir
-  , io
-  , mapIO
-  , replaceSingleDot
-  , stripPrefix
-  , takeDirName
-  ) where
+    ( io
+    , mapIO
+    , lsequence
 
-import Data.Maybe (fromMaybe)
-import Data.Tuple (fst)
+    , (⚡)
+    , (⚡⚡)
+    ) where
+
+import Data.Aeson (FromJSON, ToJSON, fromJSON)
+import Data.Text (Text)
 import Flow
 import Shikensu.Types
-import System.FilePath
 
-import qualified Data.List as List (map, stripPrefix)
-import qualified System.FilePath.Glob as Glob
+import qualified Data.Aeson as Json (Object, Result(..), encode)
+import qualified Data.HashMap.Strict as HashMap (lookup)
+import qualified Data.List as List (unzip, zip)
+import qualified Data.Tuple as Tuple (fst, snd)
+import qualified Data.Text as Text (concat, unpack)
+import qualified Data.Text.Lazy as Lazy.Text (unpack)
+import qualified Data.Text.Lazy.Encoding as Lazy.Text (decodeUtf8)
 
 
-{-| "Clean up" a path.
-
-> `/directory/./nested/` -> `directory/nested`
-> `./` -> ``
-> `.` -> ``
-
--}
-cleanPath :: FilePath -> FilePath
-cleanPath = normalise .> dropTrailingPathSeparator .> dropDrive .> replaceSingleDot
+-- IO
 
 
-{-| Get the common directory from a Pattern.
+{-| IO Sequence helpers
 -}
-commonDirectory :: Pattern -> FilePath
-commonDirectory pattern = (Glob.compile .> Glob.commonDirectory .> fst) pattern
+io :: ([Definition] -> [IO Definition]) -> Dictionary -> IO Dictionary
+io fn =
+    fn .> sequence
 
 
-{-| Compile a list of `Pattern`s to `Glob.Pattern`s.
--}
-compilePatterns :: [Pattern] -> [Glob.Pattern]
-compilePatterns = List.map Glob.compile
+mapIO :: (Definition -> IO Definition) -> Dictionary -> IO Dictionary
+mapIO =
+    fmap .> io
 
 
-{-| Path to parent, when there is one.
+{-| One way to deal with multiple dictionaries.
 
-> Just "../" or Nothing
+> lsequence
+>     [ ( "pages", Shikensu.list rootDir ["src/pages/**/*.html"]    )
+>     , ( "js",    Shikensu.list rootDir ["src/javascript/**/*.js"] )
+>     ]
 
+From multiple IO monads to a single IO monad.
 -}
-compileParentPath :: FilePath -> Maybe FilePath
-compileParentPath dirname =
-  case dirname of
-    "" -> Nothing
-    _  -> Just "../"
+lsequence :: Monad m => [( String, m a )] -> m [( String, a )]
+lsequence list =
+    let
+        unzippedList =
+            List.unzip list
 
+        identifiers =
+            Tuple.fst unzippedList
 
-{-| Path to root.
+        dictionaries =
+            Tuple.snd unzippedList
+    in
+        dictionaries
+            |> sequence
+            |> fmap (List.zip identifiers)
 
-Example, if `dirname` is 'example/subdir',
-then this will be `../../`.
 
-If the `dirname` is empty,
-then this will be empty as well.
 
--}
-compilePathToRoot :: FilePath -> FilePath
-compilePathToRoot dirname =
-  if dirname == "" then
-    ""
-  else
-    dirname
-      |> splitDirectories
-      |> fmap (\_ -> "..")
-      |> joinPath
-      |> addTrailingPathSeparator
+-- PURE
 
 
-{-| List contents of a directory using a glob pattern.
-Returns a relative path, based on the given rootDirname.
+{-| Get stuff out of the metadata.
+    Return a `Maybe`.
 -}
-globDir :: FilePath -> [Glob.Pattern] -> IO [[FilePath]]
-globDir rootDir patterns =
-  Glob.globDir patterns rootDir
-    |> fmap (fst)
-    |> fmap (List.map . List.map . makeRelative $ rootDir)
+(⚡) :: (FromJSON a, ToJSON a) => Metadata -> Text -> Maybe a
+(⚡) obj key =
+    HashMap.lookup key obj
+        |> fmap fromJSON
+        |> fmap fromJSONResult
 
 
-{-| IO Sequence helpers
+{-| Get stuff out of the metadata.
+    Does NOT return a `Maybe`, but gives an error if it isn't found.
 -}
-io :: ([Definition] -> [IO Definition]) -> Dictionary -> IO Dictionary
-io fn = sequence . fn
+(⚡⚡) :: (FromJSON a, ToJSON a) => Metadata -> Text -> a
+(⚡⚡) obj key =
+    case (obj ⚡ key) of
+        Just x  -> x
+        Nothing -> error <|
+            "Could not find the key `" ++ (Text.unpack key)         ++ "` " ++
+            "on the metadata object `" ++ (aesonObjectToString obj) ++ "` using (⚡⚡)"
 
 
-mapIO :: (Definition -> IO Definition) -> Dictionary -> IO Dictionary
-mapIO = io . fmap
 
-
-{-| If the path is a single dot, return an empty string.
-Otherwise return the path.
--}
-replaceSingleDot :: String -> String
-replaceSingleDot path = if path == "." then "" else path
+-- Private
 
 
-{-| Strip prefix.
--}
-stripPrefix :: String -> String -> String
-stripPrefix prefix target = fromMaybe target (List.stripPrefix prefix target)
+fromJSONResult :: ToJSON a => Json.Result a -> a
+fromJSONResult result =
+    case result of
+        Json.Success x -> x
+        Json.Error err -> error err
 
 
-{-| Take dirname.
--}
-takeDirName :: FilePath -> FilePath
-takeDirName = replaceSingleDot . takeDirectory
+aesonObjectToString :: Json.Object -> String
+aesonObjectToString =
+    Json.encode .> Lazy.Text.decodeUtf8 .> Lazy.Text.unpack
diff --git a/tests/Test.hs b/tests/Test.hs
--- a/tests/Test.hs
+++ b/tests/Test.hs
@@ -6,16 +6,18 @@
 import Test.Helpers (ioErrorHandler, rootPath)
 import Test.Shikensu
 import Test.Tasty
+import Test.Utilities
 
 
 main :: IO ()
 main =
-  rootPath
-    >>= \r -> catch
-      (removeDirectoryRecursive (combine r "tests/build"))
-      (ioErrorHandler)
-    >> defaultMain tests
+    rootPath
+        >>= \r -> catch
+            (removeDirectoryRecursive (combine r "tests/build"))
+            (ioErrorHandler)
+        >> defaultMain tests
 
 
 tests :: TestTree
-tests = testGroup "Tests" [shikensuTests, contribTests, exampleTests]
+tests =
+    testGroup "Tests" [shikensuTests, contribTests, exampleTests, utilityTests]
diff --git a/tests/Test/Contrib.hs b/tests/Test/Contrib.hs
--- a/tests/Test/Contrib.hs
+++ b/tests/Test/Contrib.hs
@@ -23,18 +23,18 @@
 
 contribTests :: TestTree
 contribTests = testGroup
-  "Contrib tests"
-  [ testClone
-  , testExclude
-  , testMetadata
-  , testPermalink
-  , testPrefixDirname
-  , testRead
-  , testRename
-  , testRenameExt
-  , testRenderContent
-  , testWrite
-  ]
+    "Contrib tests"
+    [ testClone
+    , testExclude
+    , testMetadata
+    , testPermalink
+    , testPrefixDirname
+    , testRead
+    , testRename
+    , testRenameExt
+    , testRenderContent
+    , testWrite
+    ]
 
 
 
@@ -43,22 +43,24 @@
 
 
 list :: Shikensu.Pattern -> IO Shikensu.Dictionary
-list pattern = rootPath >>= Shikensu.list [pattern]
+list pattern =
+    rootPath >>= Shikensu.listF [pattern]
 
 
 example_md :: IO Shikensu.Dictionary
-example_md = list "tests/fixtures/example.md"
+example_md =
+    list "tests/fixtures/example.md"
 
 
 renderer :: Shikensu.Definition -> Maybe ByteString
 renderer def =
-  let
-    openingTag = BS.pack "<html>"
-    closingTag = BS.pack "</html>"
-  in
-    def
-      |> Shikensu.content
-      |> fmap (\c -> BS.intercalate B.empty [openingTag, c, closingTag])
+    let
+        openingTag = BS.pack "<html>"
+        closingTag = BS.pack "</html>"
+    in
+        def
+            |> Shikensu.content
+            |> fmap (\c -> BS.intercalate B.empty [openingTag, c, closingTag])
 
 
 
@@ -68,175 +70,175 @@
 
 testClone :: TestTree
 testClone =
-  let
-    dictionary = fmap (Contrib.clone "example.md" "cloned.md") example_md
-    definition = fmap (List.head . List.reverse) dictionary
-  in
-    testCase "Should `clone`"
-      $ definition `rmap` Shikensu.localPath >>= assertEq "cloned.md"
+    let
+        dictionary = fmap (Contrib.clone "example.md" "cloned.md") example_md
+        definition = fmap (List.head . List.reverse) dictionary
+    in
+        testCase "Should `clone`"
+        $ definition `rmap` Shikensu.localPath >>= assertEq "cloned.md"
 
 
 
 testExclude :: TestTree
 testExclude =
-  let
-    dictionary = fmap (Contrib.exclude "example.md") example_md
-    length_ = fmap length dictionary
-  in
-    testCase "Should `exclude`"
-      $ length_ >>= assertEq 0
+    let
+        dictionary = fmap (Contrib.exclude "example.md") example_md
+        length_ = fmap length dictionary
+    in
+        testCase "Should `exclude`"
+        $ length_ >>= assertEq 0
 
 
 
 testMetadata :: TestTree
 testMetadata =
-  let
-    keyA        = Text.pack "title"
-    valueA      = Aeson.String (Text.pack "Hello world!")
+    let
+        keyA        = Text.pack "title"
+        valueA      = Aeson.String (Text.pack "Hello world!")
 
-    keyB        = Text.pack "hello"
-    valueB      = Aeson.String (Text.pack "Guardian.")
+        keyB        = Text.pack "hello"
+        valueB      = Aeson.String (Text.pack "Guardian.")
 
-    keyC        = Text.pack "removed"
-    valueC      = Aeson.String (Text.pack "Me.")
+        keyC        = Text.pack "removed"
+        valueC      = Aeson.String (Text.pack "Me.")
 
-    keyBase     = Text.pack "basename"
-    valueBase   = Aeson.String (Text.pack "example")
+        keyBase     = Text.pack "basename"
+        valueBase   = Aeson.String (Text.pack "example")
 
-    -- 1. Insert C
-    -- 2. Replace with A
-    -- 3. Insert B
-    dictionary = example_md
-      <&> ( Contrib.insertMetadata (HashMap.fromList [ (keyC, valueC) ])
-         .> Contrib.replaceMetadata (HashMap.fromList [ (keyA, valueA) ])
-         .> Contrib.copyPropsToMetadata
-         .> Contrib.insertMetadata (HashMap.fromList [ (keyB, valueB) ])
-      )
+        -- 1. Insert C
+        -- 2. Replace with A
+        -- 3. Insert B
+        dictionary = example_md
+            <&> ( Contrib.insertMetadata (HashMap.fromList [ (keyC, valueC) ])
+               .> Contrib.replaceMetadata (HashMap.fromList [ (keyA, valueA) ])
+               .> Contrib.copyPropsToMetadata
+               .> Contrib.insertMetadata (HashMap.fromList [ (keyB, valueB) ])
+            )
 
-    definition  = fmap (List.head . List.reverse) dictionary
+        definition = fmap (List.head . List.reverse) dictionary
 
-    lookupTitle = \def -> HashMap.lookup keyA (Shikensu.metadata def)
-    lookupHello = \def -> HashMap.lookup keyB (Shikensu.metadata def)
-    lookupRemoved = \def -> HashMap.lookup keyC (Shikensu.metadata def)
-    lookupBasename = \def -> HashMap.lookup keyBase (Shikensu.metadata def)
-  in
-    testGroup
-      "Metadata"
-      [ testCase "Should no longer have `removed` key"
-        $ definition `rmap` lookupRemoved >>= assertEq Nothing
+        lookupTitle = \def -> HashMap.lookup keyA (Shikensu.metadata def)
+        lookupHello = \def -> HashMap.lookup keyB (Shikensu.metadata def)
+        lookupRemoved = \def -> HashMap.lookup keyC (Shikensu.metadata def)
+        lookupBasename = \def -> HashMap.lookup keyBase (Shikensu.metadata def)
+    in
+        testGroup
+            "Metadata"
+            [ testCase "Should no longer have `removed` key"
+            $ definition `rmap` lookupRemoved >>= assertEq Nothing
 
-      , testCase "Should have `hello` key"
-        $ definition `rmap` lookupHello >>= assertEq (Just valueB)
+            , testCase "Should have `hello` key"
+            $ definition `rmap` lookupHello >>= assertEq (Just valueB)
 
-      , testCase "Should have `title` key"
-        $ definition `rmap` lookupTitle >>= assertEq (Just valueA)
+            , testCase "Should have `title` key"
+            $ definition `rmap` lookupTitle >>= assertEq (Just valueA)
 
-      , testCase "Should have `basename` key"
-        $ definition `rmap` lookupBasename >>= assertEq (Just valueBase)
-      ]
+            , testCase "Should have `basename` key"
+            $ definition `rmap` lookupBasename >>= assertEq (Just valueBase)
+            ]
 
 
 
 testPermalink :: TestTree
 testPermalink =
-  let
-    dictionary = fmap (Contrib.permalink "index") example_md
-    definition = fmap (List.head) dictionary
-  in
-    testGroup
-      "Permalink"
-      [ testCase "Should have the correct `localPath`"
-        $ definition `rmap` Shikensu.localPath >>= assertEq "example/index.md"
+    let
+        dictionary = fmap (Contrib.permalink "index") example_md
+        definition = fmap (List.head) dictionary
+    in
+        testGroup
+            "Permalink"
+            [ testCase "Should have the correct `localPath`"
+            $ definition `rmap` Shikensu.localPath >>= assertEq "example/index.md"
 
-      , testCase "Should have the correct `parentPath`"
-        $ definition `rmap` Shikensu.parentPath >>= assertEq (Just "../")
+            , testCase "Should have the correct `parentPath`"
+            $ definition `rmap` Shikensu.parentPath >>= assertEq (Just "../")
 
-      , testCase "Should have the correct `pathToRoot`"
-        $ definition `rmap` Shikensu.pathToRoot >>= assertEq "../"
-      ]
+            , testCase "Should have the correct `pathToRoot`"
+            $ definition `rmap` Shikensu.pathToRoot >>= assertEq "../"
+            ]
 
 
 
 testPrefixDirname :: TestTree
 testPrefixDirname =
-  let
-    dictionary = fmap (Contrib.prefixDirname "prefix/") (list "tests/**/example.md")
-    definition = fmap List.head dictionary
-  in
-    testGroup
-      "PrefixDirname"
-      [ testCase "Should have the correct `dirname`"
-        $ definition `rmap` Shikensu.dirname >>= assertEq "prefix/fixtures"
+    let
+        dictionary = fmap (Contrib.prefixDirname "prefix/") (list "tests/**/example.md")
+        definition = fmap List.head dictionary
+    in
+        testGroup
+            "PrefixDirname"
+            [ testCase "Should have the correct `dirname`"
+            $ definition `rmap` Shikensu.dirname >>= assertEq "prefix/fixtures"
 
-      , testCase "Should have the correct `pathToRoot`"
-        $ definition `rmap` Shikensu.pathToRoot >>= assertEq "../../"
+            , testCase "Should have the correct `pathToRoot`"
+            $ definition `rmap` Shikensu.pathToRoot >>= assertEq "../../"
 
-      , testCase "Should have the correct `parentPath`"
-        $ definition `rmap` Shikensu.parentPath >>= assertEq (Just "../")
-      ]
+            , testCase "Should have the correct `parentPath`"
+            $ definition `rmap` Shikensu.parentPath >>= assertEq (Just "../")
+            ]
 
 
 
 testRead :: TestTree
 testRead =
-  let
-    dictionary = example_md >>= Contrib.IO.read
-    definition = fmap List.head dictionary
-  in
-    testCase "Should `read`"
-      $ definition
-        <&> Shikensu.content
-        <&> fmap Text.decodeUtf8
-        >>= assertEq (Just (Text.pack "# Example\n"))
+    let
+        dictionary = example_md >>= Contrib.IO.read
+        definition = fmap List.head dictionary
+    in
+        testCase "Should `read`"
+        $ definition
+            <&> Shikensu.content
+            <&> fmap Text.decodeUtf8
+            >>= assertEq (Just (Text.pack "# Example\n"))
 
 
 
 testRename :: TestTree
 testRename =
-  let
-    dictionary = fmap (Contrib.rename "example.md" "renamed.md") example_md
-    definition = fmap (List.head) dictionary
-  in
-    testCase "Should `rename`"
-      $ definition `rmap` Shikensu.localPath >>= assertEq "renamed.md"
+    let
+        dictionary = fmap (Contrib.rename "example.md" "renamed.md") example_md
+        definition = fmap (List.head) dictionary
+    in
+        testCase "Should `rename`"
+        $ definition `rmap` Shikensu.localPath >>= assertEq "renamed.md"
 
 
 
 testRenameExt :: TestTree
 testRenameExt =
-  let
-    dictionary = fmap (Contrib.renameExt ".md" ".html") example_md
-    definition = fmap (List.head) dictionary
-  in
-    testCase "Should `renameExt`"
-      $ definition `rmap` Shikensu.extname >>= assertEq ".html"
+    let
+        dictionary = fmap (Contrib.renameExt ".md" ".html") example_md
+        definition = fmap (List.head) dictionary
+    in
+        testCase "Should `renameExt`"
+        $ definition `rmap` Shikensu.extname >>= assertEq ".html"
 
 
 
 testRenderContent :: TestTree
 testRenderContent =
-  let
-    dictionary = fmap (Contrib.renderContent renderer) (example_md >>= Contrib.IO.read)
-    definition = fmap (List.head) dictionary
-    expectedResult = Just (Text.pack "<html># Example\n</html>")
-  in
-    testCase "Should `renderContent`"
-      $ definition
-        <&> Shikensu.content
-        <&> fmap Text.decodeUtf8
-        >>= assertEq expectedResult
+    let
+        dictionary = fmap (Contrib.renderContent renderer) (example_md >>= Contrib.IO.read)
+        definition = fmap (List.head) dictionary
+        expectedResult = Just (Text.pack "<html># Example\n</html>")
+    in
+        testCase "Should `renderContent`"
+        $ definition
+            <&> Shikensu.content
+            <&> fmap Text.decodeUtf8
+            >>= assertEq expectedResult
 
 
 
 testWrite :: TestTree
 testWrite =
-  let
-    destination = "tests/build/"
-    dictionary = list "tests/**/example.md" >>= Contrib.IO.read >>= Contrib.IO.write destination
-    definition = fmap List.head dictionary
-  in
-    testCase "Should `write`"
-      $ definition
-          <&> Shikensu.rootDirname
-          >>= \r -> Text.readFile (joinPath [r, destination, "fixtures/example.md"])
-          >>= \c -> assertEq "# Example\n" (Text.unpack c)
+    let
+        destination = "tests/build/"
+        dictionary = list "tests/**/example.md" >>= Contrib.IO.read >>= Contrib.IO.write destination
+        definition = fmap List.head dictionary
+    in
+        testCase "Should `write`"
+        $ definition
+            <&> Shikensu.rootDirname
+            >>= \r -> Text.readFile (joinPath [r, destination, "fixtures/example.md"])
+            >>= \c -> assertEq "# Example\n" (Text.unpack c)
diff --git a/tests/Test/Example.hs b/tests/Test/Example.hs
--- a/tests/Test/Example.hs
+++ b/tests/Test/Example.hs
@@ -19,15 +19,15 @@
 
 exampleTests :: TestTree
 exampleTests =
-  let
-    path = canonicalizePath "./tests"
-    dict = path >>= dictionary_io
-    test = path >>= \p ->
-      read [Shikensu.makeDefinition p "fixtures/*.md" "fixtures/example.md"]
-      >>= flow
-  in
-    testCase "Example test"
-      $ dict >>= \d -> test >>= assertEq d
+    let
+        path = canonicalizePath "./tests"
+        dict = path >>= dictionary_io
+        test = path >>= \p ->
+            read [Shikensu.makeDefinition p "fixtures/*.md" "fixtures/example.md"]
+            >>= flow
+    in
+        testCase "Example test"
+        $ dict >>= \d -> test >>= assertEq d
 
 
 
@@ -36,29 +36,30 @@
 
 dictionary_io :: String -> IO Dictionary
 dictionary_io absolutePathToCwd =
-  Shikensu.list ["fixtures/*.md"] absolutePathToCwd
-    >>= read
-    >>= flow
-    >>= write "./build"
+    Shikensu.list absolutePathToCwd ["fixtures/*.md"]
+        >>= read
+        >>= flow
+        >>= write "./build"
 
 
 flow :: Dictionary -> IO Dictionary
 flow =
-     renameExt ".md" ".html"
-  .> permalink "index"
-  .> clone "index.html" "200.html"
-  .> copyPropsToMetadata
-  .> renderContent markdownRenderer
-  .> return
+       renameExt ".md" ".html"
+    .> permalink "index"
+    .> clone "index.html" "200.html"
+    .> copyPropsToMetadata
+    .> renderContent markdownRenderer
+    .> return
 
 
 markdownRenderer :: Definition -> Maybe ByteString
 markdownRenderer def =
-  content def
-    |> fmap Text.decodeUtf8
-    |> fmap renderMarkdown
-    |> fmap Text.encodeUtf8
+    content def
+        |> fmap Text.decodeUtf8
+        |> fmap renderMarkdown
+        |> fmap Text.encodeUtf8
 
 
 renderMarkdown :: Text -> Text
-renderMarkdown text = text
+renderMarkdown text =
+    text
diff --git a/tests/Test/Helpers.hs b/tests/Test/Helpers.hs
--- a/tests/Test/Helpers.hs
+++ b/tests/Test/Helpers.hs
@@ -1,12 +1,12 @@
 module Test.Helpers
-  ( (<&>)
-  , rmap
-  , assertEq
-  , ioErrorHandler
-  , rootPath
-  , sort
-  , testsPath
-  ) where
+    ( (<&>)
+    , rmap
+    , assertEq
+    , ioErrorHandler
+    , rootPath
+    , sort
+    , testsPath
+    ) where
 
 import Shikensu.Sorting (sortByAbsolutePath)
 import Shikensu.Types (Dictionary)
@@ -18,28 +18,35 @@
 
 
 (<&>) :: Functor f => f a -> (a -> b) -> f b
-(<&>) = flip fmap
+(<&>) =
+    flip fmap
 
 
 rmap :: Functor f => f a -> (a -> b) -> f b
-rmap = (<&>)
+rmap =
+    (<&>)
 
 
 assertEq :: (Eq a, Show a) => a -> a -> Assertion
-assertEq = assertEqual ""
+assertEq =
+    assertEqual ""
 
 
 ioErrorHandler :: IOError -> IO ()
-ioErrorHandler _ = putStrLn ""
+ioErrorHandler _ =
+    putStrLn ""
 
 
 rootPath :: IO FilePath
-rootPath = canonicalizePath "./"
+rootPath =
+    canonicalizePath "./"
 
 
 sort :: Dictionary -> Dictionary
-sort = List.sortBy sortByAbsolutePath
+sort =
+    List.sortBy sortByAbsolutePath
 
 
 testsPath :: IO FilePath
-testsPath = fmap ((flip combine) "tests") rootPath
+testsPath =
+    fmap ((flip combine) "tests") rootPath
diff --git a/tests/Test/Shikensu.hs b/tests/Test/Shikensu.hs
--- a/tests/Test/Shikensu.hs
+++ b/tests/Test/Shikensu.hs
@@ -11,8 +11,8 @@
 
 shikensuTests :: TestTree
 shikensuTests = testGroup
-  "Shikensu tests"
-  [testRegular, testDot, testWithoutWd, testRootFile]
+    "Shikensu tests"
+    [testRegular, testDot, testWithoutWd, testRootFile]
 
 
 
@@ -22,119 +22,119 @@
 
 testRegular :: TestTree
 testRegular =
-  let
-    pattern = "tests/**/*.md"
-    dictionary = fmap sort $ rootPath >>= Shikensu.list [pattern]
-    definition = fmap List.head dictionary
-    localPath = "fixtures/example.md"
-  in
-    testGroup "Test regular"
-      [ testCase "Should have the correct basename"
-        $ definition `rmap` Shikensu.basename >>= assertEq "example"
+    let
+        pattern = "tests/**/*.md"
+        dictionary = fmap sort $ rootPath >>= Shikensu.listF [pattern]
+        definition = fmap List.head dictionary
+        localPath = "fixtures/example.md"
+    in
+        testGroup "Test regular"
+            [ testCase "Should have the correct basename"
+            $ definition `rmap` Shikensu.basename >>= assertEq "example"
 
-      , testCase "Should have the correct dirname"
-        $ definition `rmap` Shikensu.dirname >>= assertEq "fixtures"
+            , testCase "Should have the correct dirname"
+            $ definition `rmap` Shikensu.dirname >>= assertEq "fixtures"
 
-      , testCase "Should have the correct extname"
-        $ definition `rmap` Shikensu.extname >>= assertEq ".md"
+            , testCase "Should have the correct extname"
+            $ definition `rmap` Shikensu.extname >>= assertEq ".md"
 
-      , testCase "Should have the correct localPath"
-        $ definition `rmap` Shikensu.localPath >>= assertEq localPath
+            , testCase "Should have the correct localPath"
+            $ definition `rmap` Shikensu.localPath >>= assertEq localPath
 
-      , testCase "Should have the correct pattern"
-        $ definition `rmap` Shikensu.pattern >>= assertEq pattern
+            , testCase "Should have the correct pattern"
+            $ definition `rmap` Shikensu.pattern >>= assertEq pattern
 
-      , testCase "Should have the correct workingDirname"
-        $ definition `rmap` Shikensu.workingDirname >>= assertEq "tests"
+            , testCase "Should have the correct workingDirname"
+            $ definition `rmap` Shikensu.workingDirname >>= assertEq "tests"
 
-      ]
+            ]
 
 
 testDot :: TestTree
 testDot =
-  let
-    pattern = "./tests/**/*.md"
-    dictionary = fmap sort $ rootPath >>= Shikensu.list [pattern]
-    definition = fmap List.head dictionary
-    localPath = "fixtures/example.md"
-  in
-    testGroup "Test dot"
-      [ testCase "Should have the correct basename"
-        $ definition `rmap` Shikensu.basename >>= assertEq "example"
+    let
+        pattern = "./tests/**/*.md"
+        dictionary = fmap sort $ rootPath >>= Shikensu.listF [pattern]
+        definition = fmap List.head dictionary
+        localPath = "fixtures/example.md"
+    in
+        testGroup "Test dot"
+            [ testCase "Should have the correct basename"
+            $ definition `rmap` Shikensu.basename >>= assertEq "example"
 
-      , testCase "Should have the correct dirname"
-        $ definition `rmap` Shikensu.dirname >>= assertEq "fixtures"
+            , testCase "Should have the correct dirname"
+            $ definition `rmap` Shikensu.dirname >>= assertEq "fixtures"
 
-      , testCase "Should have the correct extname"
-        $ definition `rmap` Shikensu.extname >>= assertEq ".md"
+            , testCase "Should have the correct extname"
+            $ definition `rmap` Shikensu.extname >>= assertEq ".md"
 
-      , testCase "Should have the correct localPath"
-        $ definition `rmap` Shikensu.localPath >>= assertEq localPath
+            , testCase "Should have the correct localPath"
+            $ definition `rmap` Shikensu.localPath >>= assertEq localPath
 
-      , testCase "Should have the correct pattern"
-        $ definition `rmap` Shikensu.pattern >>= assertEq pattern
+            , testCase "Should have the correct pattern"
+            $ definition `rmap` Shikensu.pattern >>= assertEq pattern
 
-      , testCase "Should have the correct workingDirname"
-        $ definition `rmap` Shikensu.workingDirname >>= assertEq "tests"
+            , testCase "Should have the correct workingDirname"
+            $ definition `rmap` Shikensu.workingDirname >>= assertEq "tests"
 
-      ]
+            ]
 
 
 testWithoutWd :: TestTree
 testWithoutWd =
-  let
-    pattern = "**/*.md"
-    dictionary = fmap sort $ testsPath >>= Shikensu.list [pattern]
-    definition = fmap List.head dictionary
-    localPath = "fixtures/example.md"
-  in
-    testGroup "Test without workingDirname"
-      [ testCase "Should have the correct basename"
-        $ definition `rmap` Shikensu.basename >>= assertEq "example"
+    let
+        pattern = "**/*.md"
+        dictionary = fmap sort $ testsPath >>= Shikensu.listF [pattern]
+        definition = fmap List.head dictionary
+        localPath = "fixtures/example.md"
+    in
+        testGroup "Test without workingDirname"
+            [ testCase "Should have the correct basename"
+            $ definition `rmap` Shikensu.basename >>= assertEq "example"
 
-      , testCase "Should have the correct dirname"
-        $ definition `rmap` Shikensu.dirname >>= assertEq "fixtures"
+            , testCase "Should have the correct dirname"
+            $ definition `rmap` Shikensu.dirname >>= assertEq "fixtures"
 
-      , testCase "Should have the correct extname"
-        $ definition `rmap` Shikensu.extname >>= assertEq ".md"
+            , testCase "Should have the correct extname"
+            $ definition `rmap` Shikensu.extname >>= assertEq ".md"
 
-      , testCase "Should have the correct localPath"
-        $ definition `rmap` Shikensu.localPath >>= assertEq localPath
+            , testCase "Should have the correct localPath"
+            $ definition `rmap` Shikensu.localPath >>= assertEq localPath
 
-      , testCase "Should have the correct pattern"
-        $ definition `rmap` Shikensu.pattern >>= assertEq pattern
+            , testCase "Should have the correct pattern"
+            $ definition `rmap` Shikensu.pattern >>= assertEq pattern
 
-      , testCase "Should have the correct workingDirname"
-        $ definition `rmap` Shikensu.workingDirname >>= assertEq ""
+            , testCase "Should have the correct workingDirname"
+            $ definition `rmap` Shikensu.workingDirname >>= assertEq ""
 
-      ]
+            ]
 
 
 testRootFile :: TestTree
 testRootFile =
-  let
-    pattern = "*.md"
-    dictionary = fmap sort $ rootPath >>= Shikensu.list [pattern]
-    definition = fmap List.head dictionary
-    localPath = "README.md"
-  in
-    testGroup "Test file in root path"
-      [ testCase "Should have the correct basename"
-        $ definition `rmap` Shikensu.basename >>= assertEq "README"
+    let
+        pattern = "*.md"
+        dictionary = fmap sort $ rootPath >>= Shikensu.listF [pattern]
+        definition = fmap List.head dictionary
+        localPath = "CHANGELOG.md"
+    in
+        testGroup "Test file in root path"
+            [ testCase "Should have the correct basename"
+            $ definition `rmap` Shikensu.basename >>= assertEq "CHANGELOG"
 
-      , testCase "Should have the correct dirname"
-        $ definition `rmap` Shikensu.dirname >>= assertEq ""
+            , testCase "Should have the correct dirname"
+            $ definition `rmap` Shikensu.dirname >>= assertEq ""
 
-      , testCase "Should have the correct extname"
-        $ definition `rmap` Shikensu.extname >>= assertEq ".md"
+            , testCase "Should have the correct extname"
+            $ definition `rmap` Shikensu.extname >>= assertEq ".md"
 
-      , testCase "Should have the correct localPath"
-        $ definition `rmap` Shikensu.localPath >>= assertEq localPath
+            , testCase "Should have the correct localPath"
+            $ definition `rmap` Shikensu.localPath >>= assertEq localPath
 
-      , testCase "Should have the correct pattern"
-        $ definition `rmap` Shikensu.pattern >>= assertEq pattern
+            , testCase "Should have the correct pattern"
+            $ definition `rmap` Shikensu.pattern >>= assertEq pattern
 
-      , testCase "Should have the correct workingDirname"
-        $ definition `rmap` Shikensu.workingDirname >>= assertEq ""
+            , testCase "Should have the correct workingDirname"
+            $ definition `rmap` Shikensu.workingDirname >>= assertEq ""
 
-      ]
+            ]
diff --git a/tests/Test/Utilities.hs b/tests/Test/Utilities.hs
new file mode 100644
--- /dev/null
+++ b/tests/Test/Utilities.hs
@@ -0,0 +1,69 @@
+module Test.Utilities (utilityTests) where
+
+import Flow
+import Shikensu.Types
+import Shikensu.Utilities as Utils
+import Test.Helpers
+import Test.Tasty
+import Test.Tasty.HUnit
+
+import qualified Data.HashMap.Strict as HashMap (singleton)
+import qualified Data.List as List (head)
+import qualified Data.Tuple as Tuple (fst)
+import qualified Shikensu
+import qualified Shikensu.Contrib as Contrib
+
+
+utilityTests :: TestTree
+utilityTests = testGroup
+    "Utility tests"
+    [testSequencing, testThunder]
+
+
+
+
+-- Tests
+
+
+testSequencing :: TestTree
+testSequencing =
+    let
+        result =
+            Utils.lsequence
+                [ ( "a", rootPath >>= Shikensu.listF ["tests/fixtures/example.md"] )
+                , ( "b", rootPath >>= Shikensu.listF ["tests/fixtures/example.md"] )
+                ]
+    in
+        testCase "Test lsequence"
+        $ (List.head .> Tuple.fst) <$> result >>= assertEq "a"
+
+
+testThunder :: TestTree
+testThunder =
+    let
+        flow =
+            Contrib.insertMetadata (HashMap.singleton "a" "Hi!")
+            .> return
+
+        dictionary =
+            rootPath
+                >>= Shikensu.listF ["tests/fixtures/example.md"]
+                >>= flow
+
+        def =
+            fmap List.head dictionary
+
+        resultExisting =
+            fmap (\d -> metadata d ⚡ "a" :: Maybe String) def
+
+        resultNonExisting =
+            fmap (\d -> metadata d ⚡ "b" :: Maybe String) def
+    in
+        testGroup
+            "Test (⚡)"
+            [ testCase "Existing"
+            $ resultExisting >>= assertEq (Just "Hi!")
+
+            , testCase "Non-existing"
+            $ resultNonExisting >>= assertEq (Nothing)
+            ]
