diff --git a/Kawaii-Parser.cabal b/Kawaii-Parser.cabal
--- a/Kawaii-Parser.cabal
+++ b/Kawaii-Parser.cabal
@@ -11,9 +11,9 @@
 maintainer: liisikerik@hotmail.com
 name: Kawaii-Parser
 synopsis: A simple parsing library and some additional utilities.
-version: 4.0.0
+version: 5.0.0
 library
-  build-depends: base < 4.21, containers, directory, mtl, transformers
+  build-depends: base < 4.22, containers, directory, mtl, transformers
   default-extensions: FlexibleContexts, ScopedTypeVariables, StandaloneDeriving
   default-language: Haskell2010
   exposed-modules: Parser.Files, Parser.Locations, Parser.Parser, Parser.Utilities
diff --git a/Parser/Files.hs b/Parser/Files.hs
--- a/Parser/Files.hs
+++ b/Parser/Files.hs
@@ -1,24 +1,24 @@
 {-|
-Description: Relative directories and file paths.
-
-* Relative directories and file paths.
+Relative directories and file paths.
 -}
 module Parser.Files (
   Back (..),
   Directory (..),
-  Error (..),
   Ext,
+  File_error (..),
   File_path (..),
   File_path_and_location (..),
   (<//>),
   drop_file_name,
-  parse_file_path,
+  parse_file_path',
   read_file,
   write_file,
+  write_file_path,
   write_file_path_and_location) where
   import Control.Monad
   import Control.Monad.Except
   import Control.Monad.IO.Class
+  import Data.Bifunctor
   import Data.Char
   import Data.Maybe
   import Parser.Locations
@@ -31,15 +31,16 @@
   -- | Relative directory.
   data Directory = Directory [Back] [String]
   -- | Errors.
-  data Error = Failed_to_find_the_file FilePath | Invalid_file_path | Unexpected_file_extension Ext
+  data File_error = Failed_to_find_the_file FilePath | Invalid_file_path | Unexpected_extension Ext
+  -- | File extensions.
   type Ext = String
   -- | Relative file path.
   data File_path = File_path Directory String Ext
   -- | Locations with a file path.
   data File_path_and_location = File_path_and_location File_path Location
-  type Parser = Parser' Token Error
+  type Parser = Parser' Token File_error
   data Token = Dot_token | Name_token String | Slash_token
-  type Tokeniser = Tokeniser' Char_class Token Error
+  type Tokeniser = Tokeniser' Char_class Token File_error
   -- | Prepend a directory to file path.
   infixr 6 <//>
   (<//>) :: Directory -> File_path -> File_path
@@ -63,13 +64,13 @@
   deriving instance Show Back
   deriving instance Show Char_class
   deriving instance Show Directory
-  deriving instance Show Error
+  deriving instance Show File_error
   deriving instance Show File_path
   deriving instance Show File_path_and_location
   deriving instance Show Token
-  check_ext :: (MonadError Error f) => Ext -> File_path -> f ()
-  check_ext expected_ext (File_path _ _ actual_ext) = check (Unexpected_file_extension actual_ext) (expected_ext == actual_ext)
-  check_file_path :: (MonadError Error f) => Ext -> File_path -> f ()
+  check_ext :: (MonadError File_error f) => Ext -> File_path -> f ()
+  check_ext expected_ext (File_path _ _ actual_ext) = check (Unexpected_extension actual_ext) (expected_ext == actual_ext)
+  check_file_path :: (MonadError File_error f) => Ext -> File_path -> f ()
   check_file_path ext file_path =
     do
       check Invalid_file_path (valid_file_path file_path)
@@ -108,21 +109,23 @@
   parse_directory = Directory <$> parse_many (parse_with_slash parse_back) <*> parse_many (parse_with_slash parse_name)
   parse_dot :: Parser ()
   parse_dot = parse_token Dot_token
-  -- | Parse a file path and check the extension.
-  parse_file_path :: Ext -> String -> Either Error File_path
-  parse_file_path expected_ext file_path =
+  parse_file_path :: Parser File_path
+  parse_file_path =
     do
-      file_path' <- fromJust (parse' classify_char (\ _ -> id) tokenise parse_file_path' (\ _ -> Invalid_file_path) file_path)
-      check_ext expected_ext file_path'
-      return file_path' where
-    parse_file_path' :: Parser File_path
-    parse_file_path' =
-      do
-        directory <- parse_directory
-        file_name <- parse_name
-        parse_dot
-        actual_ext <- parse_name
-        return (File_path directory file_name actual_ext)
+      directory <- parse_directory
+      file_name <- parse_name
+      parse_dot
+      actual_ext <- parse_name
+      return (File_path directory file_name actual_ext)
+  -- | Parse a file path and check the extension.
+  parse_file_path' :: (File_error -> error) -> Ext -> String -> Either error File_path
+  parse_file_path' transform_error expected_ext file_path =
+    first
+      transform_error
+      (do
+        file_path' <- fromJust (parse' classify_char (\ _ -> id) tokenise parse_file_path (\ _ -> Invalid_file_path) file_path)
+        check_ext expected_ext file_path'
+        return file_path')
   parse_name :: Parser String
   parse_name = parse_token' name_token
   parse_with_slash :: Parser t -> Parser t
@@ -132,15 +135,17 @@
       parse_token Slash_token
       return x
   -- | Check the extension and read the file.
-  read_file :: Ext -> File_path -> ExceptT Error IO String
-  read_file ext file_path =
-    do
-      check_file_path ext file_path
-      let file_path' = write_file_path file_path
-      file_exits <- liftIO (doesPathExist file_path')
-      case file_exits of
-        False -> throwError (Failed_to_find_the_file file_path')
-        True -> liftIO (readFile file_path')
+  read_file :: Ext -> (FilePath -> IO file) -> (File_error -> error) -> File_path -> ExceptT error IO file
+  read_file ext read_file' transform_error file_path =
+    withExceptT
+      transform_error
+      (do
+        check_file_path ext file_path
+        let file_path' = write_file_path file_path
+        file_exits <- liftIO (doesPathExist file_path')
+        case file_exits of
+          False -> throwError (Failed_to_find_the_file file_path')
+          True -> liftIO (read_file' file_path'))
   tokenise :: Tokeniser ()
   tokenise = void (parse_many tokenise_1)
   tokenise_1 :: Tokeniser ()
@@ -163,13 +168,17 @@
   write_directory :: Directory -> FilePath
   write_directory (Directory back directories) = join (write_with_slash <$> ((write_back <$> back) <> directories))
   -- | Check the extension and write to the file.
-  write_file :: Ext -> File_path -> String -> ExceptT Error IO ()
-  write_file ext file_path file =
-    do
-      check_file_path ext file_path
-      liftIO (writeFile (write_file_path file_path) file)
+  write_file :: Ext -> (FilePath -> file -> IO ()) -> (File_error -> error) -> File_path -> file -> ExceptT error IO ()
+  write_file ext write_file' transform_error file_path file =
+    withExceptT
+      transform_error
+      (do
+        check_file_path ext file_path
+        liftIO (write_file' (write_file_path file_path) file))
+  -- | Write file path.
   write_file_path :: File_path -> FilePath
   write_file_path (File_path directory file_name ext) = write_directory directory <> file_name <> "." <> ext
+  -- | Write file path and location.
   write_file_path_and_location :: File_path -> Location -> String
   write_file_path_and_location file_path location = write_file_path file_path <> ":" <> write_location location
   write_with_slash :: String -> String
diff --git a/Parser/Locations.hs b/Parser/Locations.hs
--- a/Parser/Locations.hs
+++ b/Parser/Locations.hs
@@ -1,7 +1,5 @@
 {-|
-Description: Locations.
-
-* Locations.
+Locations.
 -}
 module Parser.Locations (
   Location,
@@ -13,7 +11,7 @@
   deriving instance Eq Location
   deriving instance Ord Location
   deriving instance Show Location
-  deriving instance Show t => Show (With_location t)
+  deriving instance (Show t) => Show (With_location t)
   -- | Locations.
   data Location = Location Integer Integer
   -- | Add a location to any type.
diff --git a/Parser/Parser.hs b/Parser/Parser.hs
--- a/Parser/Parser.hs
+++ b/Parser/Parser.hs
@@ -1,11 +1,10 @@
 {-|
-Description: Combinator-based tokeniser and parser with symmetric choice and location tracking.
-
-* Combinator-based tokeniser and parser with symmetric choice and location tracking.
+Combinator-based tokeniser and parser with symmetric choice and location tracking.
 -}
 module Parser.Parser (
   Parser',
   Tokeniser',
+  (<+),
   (<+>),
   add_location,
   add_token,
@@ -37,7 +36,27 @@
   -- classify characters before tokenisation to simplify patternmatching.
   type Tokeniser' char_class token error = Parser char_class [With_location token] error
   data Tokens token = Tokens [With_location token] Location
-  -- | Symmetric choice between two parsers.
+  -- | Asymmetric choice between two parsers. Picks the longer match but, unlike @<+@, picks the first result if both parsers
+  -- match the same number of tokens. Use this operator if you need to choose between two parsers that can match the same
+  -- number of tokens.
+  infixr 3 <+
+  (<+) :: (Monoid output) => Parser token output error t -> Parser token output error t -> Parser token output error t
+  Parser parse_0 <+ Parser parse_1 =
+    Parser
+      (\ tokens ->
+        do
+          result_0 <- parse_0 tokens
+          result_1 <- parse_1 tokens
+          return
+            (case (result_0, result_1) of
+              (Nothing, _) -> result_1
+              (_, Nothing) -> result_0
+              (Just (_, tokens_0), Just (_, tokens_1)) ->
+                case compare (count_tokens tokens_0) (count_tokens tokens_1) of
+                  LT -> result_0
+                  EQ -> result_0
+                  GT -> result_1))
+  -- | Symmetric choice between two parsers. Ambiguous parsing will result in an error if it's not resolved by the end.
   infixr 3 <+>
   (<+>) :: (Monoid output) => Parser token output error t -> Parser token output error t -> Parser token output error t
   Parser parse_0 <+> Parser parse_1 =
diff --git a/Parser/Utilities.hs b/Parser/Utilities.hs
--- a/Parser/Utilities.hs
+++ b/Parser/Utilities.hs
@@ -1,7 +1,5 @@
 {-|
-Description: Assorted utilities.
-
-* Assorted utilities.
+Assorted utilities.
 -}
 module Parser.Utilities (
   (<->),
@@ -21,7 +19,7 @@
   s <-> t = s <> " " <> t
   -- | Checks if all elements of a list are equal. Returns @Nothing@ if all elements aren't equal, @Just Nothing@ if the list is
   -- empty and @Just (Just x)@ if all elements are equal to @x@.
-  all_equal :: Eq t => [t] -> Maybe (Maybe t)
+  all_equal :: (Eq t) => [t] -> Maybe (Maybe t)
   all_equal x =
     case x of
       [] -> Just Nothing
@@ -30,44 +28,28 @@
           check () (all ((==) y) x')
           Just (Just y)
   -- | Check if the value is in bounds.
-  between :: Ord t => t -> t -> t -> Bool
+  between :: (Ord t) => t -> t -> t -> Bool
   between lowest highest x = lowest <= x && highest >= x
   -- | Throw an error if the condition is not satisfied.
-  check :: MonadError error f => error -> Bool -> f ()
+  check :: (MonadError error f) => error -> Bool -> f ()
   check err condition =
     case condition of
       False -> throwError err
       True -> return ()
   -- | Construct a map if all keys are different. Otherwise return @Nothing@.
-  construct_map :: Ord t => [(t, u)] -> Maybe (Map t u)
+  construct_map :: (Ord t) => [(t, u)] -> Maybe (Map t u)
   construct_map x =
     do
       let y = Map.fromList x
       check () (Foldable.length x == Map.size y)
       Just y
   -- | Construct a set if all elements are different. Otherwise return @Nothing@.
-  construct_set :: Ord t => [t] -> Maybe (Set t)
+  construct_set :: (Ord t) => [t] -> Maybe (Set t)
   construct_set x =
     do
       let y = Set.fromList x
       check () (Foldable.length x == Set.size y)
       Just y
-{-
-  -- | Safe list indexation.
-  element_at :: Int -> [t] -> Maybe t
-  element_at j x =
-    do
-      check () (between 0 (Foldable.length x - 1) j)
-      return (x !! j)
--}
   -- | Aggregate least common denominator.
   lcm_all :: (Foldable f, Integral t) => f t -> t
   lcm_all = Foldable.foldr lcm 1
-{-
-  -- | Swap Left and Right.
-  swap_either :: Either t u -> Either u t
-  swap_either x =
-    case x of
-      Left y -> Right y
-      Right y -> Left y
--}
