diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,34 @@
 Checkmate changelog
 ===================
 
+Version 0.4.0
+-------------
+
+Released on September 1, 2018.
+
+ -  Became internally independent from the [range] library.
+ -  Became to use GHC 8.4 internally.
+ -  The officially distributed executable binaries for Linux became
+    independent from [glibc] again, and statically linked to [musl] instead.
+
+[range]: https://hackage.haskell.org/package/range
+[musl]: https://www.musl-libc.org/
+
+
+Version 0.3.3
+-------------
+
+Released on May 16, 2018.
+
+ -  The officially distributed executable binaries for Linux became
+    dependent on [glibc].
+
+ -  Fixed a bug that it had failed to scan if any file in a change set is
+    deleted.
+
+[glibc]: https://www.gnu.org/software/libc/
+
+
 Version 0.3.2
 -------------
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
 
 [![Build Status][ci-badge]][ci]
 [![Hackage][hackage-badge]][hackage]
+[![GitHub release][release-badge]][latest release]
 
 Checkmate is a small program to generate human-readable checklists from
 a given patch (or pull request).  Leave `CHECK` comments (that are the same
@@ -12,10 +13,11 @@
 It helps contributors and reviewers to remind matters that require attention
 when a part of the code is changed.
 
-[ci-badge]: https://travis-ci.org/spoqa/checkmate.svg?branch=master
-[ci]: https://travis-ci.org/spoqa/checkmate
+[ci-badge]: https://travis-ci.com/dahlia/checkmate.svg?branch=master
+[ci]: https://travis-ci.com/dahlia/checkmate
 [hackage-badge]: https://img.shields.io/hackage/v/checkmate.svg
 [hackage]: https://hackage.haskell.org/package/checkmate
+[release-badge]: https://img.shields.io/github/release/dahlia/checkmate.svg?label=download&colorB=4c1
 
 
 Situation
@@ -135,10 +137,17 @@
 stack install checkmate
 ~~~~~~~~
 
-[every release]: https://github.com/spoqa/checkmate/releases
-[latest release]: https://github.com/spoqa/checkmate/releases/latest
+Note: if you experience an error like `ConnectionFailure
+Network.BSD.getProtocolByName: does not exist (no such protocol name: tcp)`
+on Debian/Ubuntu Linux, try to install [*netbase*][netbase] package.
+(Read [this explanation][1] for details.)
+
+[every release]: https://github.com/dahlia/checkmate/releases
+[latest release]: https://github.com/dahlia/checkmate/releases/latest
 [Cabal]: https://www.haskell.org/cabal/
 [Stack]: https://www.haskellstack.org/
+[netbase]: https://packages.debian.org/search?keywords=netbase
+[1]: https://github.com/commercialhaskell/stack/issues/2372#issuecomment-234113085
 
 
 Integration with CI
@@ -156,7 +165,7 @@
     of the latest release, i.e.:
 
     ~~~~~~~ bash
-    CHECKMATE_DOWNLOAD_URL=https://github.com/spoqa/checkmate/releases/download/0.3.2/checkmate-linux-x86_64
+    CHECKMATE_DOWNLOAD_URL=https://github.com/dahlia/checkmate/releases/download/0.4.0/checkmate-linux-x86_64
     ~~~~~~~
 
 [personal API tokens]: https://github.com/blog/1509-personal-api-tokens
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -1,10 +1,7 @@
 {-# LANGUAGE OverloadedStrings #-}
-import Control.Monad
 import Data.List (elemIndices)
 import Data.List.NonEmpty (nonEmpty, last)
-import Data.Maybe
 import Data.Semigroup ((<>))
-import Prelude hiding (error)
 import System.Environment
 import System.Exit
 import System.IO
diff --git a/checkmate.cabal b/checkmate.cabal
--- a/checkmate.cabal
+++ b/checkmate.cabal
@@ -1,29 +1,30 @@
--- This file has been generated from package.yaml by hpack version 0.17.1.
+-- This file has been generated from package.yaml by hpack version 0.28.2.
 --
 -- see: https://github.com/sol/hpack
+--
+-- hash: 283f7df21c88e26a8b798e9c1a8fc53f126eebb02ca0906b89696f2f25f90eca
 
 name:           checkmate
-version:        0.3.2
+version:        0.4.0
 synopsis:       Generate checklists relevant to a given patch
 category:       Development
 stability:      alpha
-homepage:       https://github.com/spoqa/checkmate#readme
-bug-reports:    https://github.com/spoqa/checkmate/issues
+homepage:       https://github.com/dahlia/checkmate#readme
+bug-reports:    https://github.com/dahlia/checkmate/issues
 author:         Hong Minhee
 maintainer:     hong.minhee@gmail.com
-copyright:      (c) 2017 Hong Minhee
+copyright:      © 2017–2018 Hong Minhee
 license:        AGPL-3
 license-file:   LICENSE
 build-type:     Simple
 cabal-version:  >= 1.10
-
 extra-source-files:
     CHANGELOG.md
     README.md
 
 source-repository head
   type: git
-  location: https://github.com/spoqa/checkmate
+  location: https://github.com/dahlia/checkmate
 
 flag static
   description: Static link
@@ -31,106 +32,112 @@
   default: False
 
 library
-  hs-source-dirs:
-      src
-  ghc-options: -Wall -fwarn-incomplete-uni-patterns
-  build-depends:
-      base >= 4.7 && < 5
-    , diff-parse >= 0.2.1 && < 0.3.0
-    , directory == 1.3.*
-    , filepath >= 1.4.1.1 && < 2.0.0
-    , megaparsec >= 5.3.1 && < 5.4.0
-    , range >= 0.1.2 && < 0.2.0
-    , text == 1.*
-    , containers >= 0.5.7.1 && < 0.6.0.0
-    , github == 0.17.*
-    , monad-parallel >= 0.7.2.2 && < 0.8.0.0
   exposed-modules:
       Checkmate.Check
-      Checkmate.Diff
       Checkmate.Discover
       Checkmate.Parser.CheckFile
       Checkmate.Parser.IndentBlock
       Checkmate.Publisher.GitHub
+      Checkmate.Range
       Checkmate.Renderer
+  other-modules:
+      Paths_checkmate
+  hs-source-dirs:
+      src
+  ghc-options: -Wall -fwarn-incomplete-uni-patterns
+  build-depends:
+      base >=4.7 && <5
+    , containers >=0.5.7.1 && <0.6.0.0
+    , diff-parse >=0.2.1 && <0.3.0
+    , directory ==1.3.*
+    , filepath >=1.4.1.1 && <2.0.0
+    , github ==0.19.*
+    , megaparsec ==6.5.*
+    , monad-parallel >=0.7.2.2 && <0.8.0.0
+    , text ==1.*
+  if os(darwin)
+    ghc-options: -Wwarn -optP-Wno-nonportable-include-path
+  else
+    ghc-options: -Wwarn
   default-language: Haskell2010
 
 executable checkmate
   main-is: Main.hs
+  other-modules:
+      Paths_checkmate
   hs-source-dirs:
       app
-  ghc-options: -Wall
   build-depends:
-      base >= 4.7 && < 5
-    , diff-parse >= 0.2.1 && < 0.3.0
-    , directory == 1.3.*
-    , filepath >= 1.4.1.1 && < 2.0.0
-    , megaparsec >= 5.3.1 && < 5.4.0
-    , range >= 0.1.2 && < 0.2.0
-    , text == 1.*
+      base >=4.7 && <5
     , checkmate
-    , optparse-applicative >= 0.13.2.0 && < 0.15.0.0
-    , process >= 1.4.3.0 && < 1.5.0.0
+    , diff-parse >=0.2.1 && <0.3.0
+    , directory ==1.3.*
+    , filepath >=1.4.1.1 && <2.0.0
+    , megaparsec ==6.5.*
+    , optparse-applicative >=0.13.2.0 && <0.15.0.0
+    , process >=1.6.1.0 && <1.7.0.0
+    , text ==1.*
+  if os(darwin)
+    ghc-options: -Wwarn -optP-Wno-nonportable-include-path
+  else
+    ghc-options: -Wwarn
   if flag(static)
-    ghc-options: -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N -static -optl-static -optl-pthread -optc-Os -fPIC
+    ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N -static -optl-static -optl-pthread -optc-Os -fPIC
   else
-    ghc-options: -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N
+    ghc-options: -Wall -fwarn-incomplete-uni-patterns -threaded -rtsopts -with-rtsopts=-N
   default-language: Haskell2010
 
 test-suite hlint
   type: exitcode-stdio-1.0
-  main-is: HLint.hs
-  hs-source-dirs:
-      test
-  ghc-options: -Wall
+  main-is: hlint.hs
+  other-modules:
+      Paths_checkmate
   build-depends:
-      base >= 4.7 && < 5
-    , diff-parse >= 0.2.1 && < 0.3.0
-    , directory == 1.3.*
-    , filepath >= 1.4.1.1 && < 2.0.0
-    , megaparsec >= 5.3.1 && < 5.4.0
-    , range >= 0.1.2 && < 0.2.0
-    , text == 1.*
-    , hlint >= 2.0.9 && < 3
+      base >=4.7 && <5
+    , diff-parse >=0.2.1 && <0.3.0
+    , directory ==1.3.*
+    , filepath >=1.4.1.1 && <2.0.0
+    , hlint >=2.0.9 && <3
+    , megaparsec ==6.5.*
+    , text ==1.*
+  if os(darwin)
+    ghc-options: -Wwarn -optP-Wno-nonportable-include-path
+  else
+    ghc-options: -Wwarn
+  default-language: Haskell2010
+
+test-suite spec
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
   other-modules:
       Checkmate.CheckSpec
-      Checkmate.DiffSpec
       Checkmate.DiscoverSpec
       Checkmate.Parser.CheckFileSpec
       Checkmate.Parser.IndentBlockSpec
+      Checkmate.RangeSpec
       Checkmate.RendererSpec
-      Spec
-  default-language: Haskell2010
-
-test-suite spec
-  type: exitcode-stdio-1.0
-  main-is: Spec.hs
+      Paths_checkmate
   hs-source-dirs:
       test
   ghc-options: -Wall -fno-warn-incomplete-uni-patterns -fno-warn-missing-signatures -rtsopts -threaded -with-rtsopts=-N -Wno-orphans
   build-depends:
-      base >= 4.7 && < 5
-    , diff-parse >= 0.2.1 && < 0.3.0
-    , directory == 1.3.*
-    , filepath >= 1.4.1.1 && < 2.0.0
-    , megaparsec >= 5.3.1 && < 5.4.0
-    , range >= 0.1.2 && < 0.2.0
-    , text == 1.*
-    , bytestring >= 0.10.8.1 && < 0.11
+      QuickCheck >=2.9.2 && <3.0.0
+    , base >=4.7 && <5
+    , bytestring >=0.10.8.1 && <0.11
     , checkmate
-    , file-embed >= 0.0.10 && < 0.1.0
-    , hspec >= 2.4.4 && < 3.0.0
-    , hspec-megaparsec >= 0.3.1 && < 0.4.0
-    , interpolatedstring-perl6 == 1.*
-    , QuickCheck >= 2.9.2 && < 3.0.0
-    , quickcheck-text >= 0.1.2.1 && < 0.2.0.0
-    , temporary >= 1.2.1 && < 1.3.0.0
-  other-modules:
-      Checkmate.CheckSpec
-      Checkmate.DiffSpec
-      Checkmate.DiscoverSpec
-      Checkmate.Parser.CheckFileSpec
-      Checkmate.Parser.IndentBlockSpec
-      Checkmate.RendererSpec
-      HLint
+    , diff-parse >=0.2.1 && <0.3.0
+    , directory ==1.3.*
+    , file-embed >=0.0.10 && <0.1.0
+    , filepath >=1.4.1.1 && <2.0.0
+    , hspec >=2.4.4 && <3.0.0
+    , hspec-megaparsec >=1.0.0 && <1.1.0
+    , interpolatedstring-perl6 ==1.*
+    , megaparsec ==6.5.*
+    , quickcheck-text >=0.1.2.1 && <0.2.0.0
+    , temporary >=1.2.1 && <1.3.0.0
+    , text ==1.*
+  if os(darwin)
+    ghc-options: -Wwarn -optP-Wno-nonportable-include-path
+  else
+    ghc-options: -Wwarn
   default-language: Haskell2010
diff --git a/hlint.hs b/hlint.hs
new file mode 100644
--- /dev/null
+++ b/hlint.hs
@@ -0,0 +1,12 @@
+import Language.Haskell.HLint
+import System.Exit
+
+arguments :: [String]
+arguments = ["app", "src", "test"]
+
+main :: IO ()
+main = do
+    hlints <- hlint arguments
+    case hlints of
+        [] -> exitSuccess
+        _ -> exitFailure
diff --git a/src/Checkmate/Check.hs b/src/Checkmate/Check.hs
--- a/src/Checkmate/Check.hs
+++ b/src/Checkmate/Check.hs
@@ -7,11 +7,12 @@
 
 import Data.Set
 import Data.Text
-import Data.Range.Range hiding (union)
 import System.FilePath
 
+import Checkmate.Range
+
 data Scope
-    = FileBlock { scopePath :: FilePath, scopeRange :: Range Int }
+    = FileBlock { scopePath :: FilePath, scopeRange :: Range }
     | Directory { scopePath :: FilePath }
     deriving (Show)
 
diff --git a/src/Checkmate/Diff.hs b/src/Checkmate/Diff.hs
deleted file mode 100644
--- a/src/Checkmate/Diff.hs
+++ /dev/null
@@ -1,11 +0,0 @@
-module Checkmate.Diff
-    ( rangeFromDiffRange
-    ) where
-
-import Data.Range.Range as Range
-import Text.Diff.Parse.Types as DT
-
-rangeFromDiffRange :: DT.Range -> Range.Range Int
-rangeFromDiffRange (DT.Range start lineLen)
-  | lineLen < 2 = Range.SingletonRange start
-  | otherwise = Range.SpanRange start $ start + (lineLen - 1)
diff --git a/src/Checkmate/Discover.hs b/src/Checkmate/Discover.hs
--- a/src/Checkmate/Discover.hs
+++ b/src/Checkmate/Discover.hs
@@ -6,8 +6,9 @@
     , parseDiff
     ) where
 
+import System.IO.Error
+
 import Control.Monad.Parallel as P
-import Data.Range.Range as Range
 import Data.Set as S
 import Data.Text
 import System.Directory
@@ -16,9 +17,9 @@
 import Text.Diff.Parse.Types
 
 import Checkmate.Check
-import Checkmate.Diff
 import Checkmate.Parser.CheckFile
 import Checkmate.Parser.IndentBlock
+import Checkmate.Range
 
 checkFileNames :: Set FilePath
 checkFileNames = fromList
@@ -69,7 +70,10 @@
 discoverFile baseDirPath FileDelta { fileDeltaContent = Hunks hunks
                                    , fileDeltaDestFile = filePathT
                                    } = do
-    result <- parseSourceFile filePath
+    result <- catchIOError (parseSourceFile filePath) $ \ e ->
+        if isDoesNotExistError e
+           then return $ Right S.empty
+           else ioError e
     return $ case result of
         Left _ -> S.empty
         Right checklist -> fromList
@@ -80,5 +84,5 @@
   where
     filePath :: FilePath
     filePath = baseDirPath </> unpack filePathT
-    ranges :: [Range.Range Int]
-    ranges = [rangeFromDiffRange r | Hunk { hunkDestRange = r } <- hunks]
+    ranges :: [Range]
+    ranges = [r | Hunk { hunkDestRange = r } <- hunks]
diff --git a/src/Checkmate/Parser/CheckFile.hs b/src/Checkmate/Parser/CheckFile.hs
--- a/src/Checkmate/Parser/CheckFile.hs
+++ b/src/Checkmate/Parser/CheckFile.hs
@@ -1,29 +1,33 @@
+{-# LANGUAGE OverloadedStrings #-}
 module Checkmate.Parser.CheckFile
-    ( parseCheckFile
+    ( ParseError
+    , parseCheckFile
     , parseCheckFileText
     , parser
     ) where
 
 import Control.Monad
+import Data.Void
 
 import Data.Set
 import qualified Data.Text as T
 import Data.Text.IO
 import System.FilePath
-import Text.Megaparsec
-import Text.Megaparsec.Text
+import Text.Megaparsec hiding (ParseError)
+import Text.Megaparsec.Char
+import qualified Text.Megaparsec.Error as E
 
 import Checkmate.Check
 
-parseCheckFile :: FilePath
-               -> IO (Either (ParseError (Token T.Text) Dec) Checklist)
+type Parser = Parsec Void T.Text
+type ParseError = E.ParseError Char Void
+
+parseCheckFile :: FilePath -> IO (Either ParseError Checklist)
 parseCheckFile filePath = do
     input <- Data.Text.IO.readFile filePath
     return $ parseCheckFileText filePath input
 
-parseCheckFileText :: FilePath
-                   -> T.Text
-                   -> Either (ParseError (Token T.Text) Dec) Checklist
+parseCheckFileText :: FilePath -> T.Text -> Either ParseError Checklist
 parseCheckFileText filePath =
     parse (parser $ takeDirectory filePath) filePath
 
@@ -53,7 +57,7 @@
     checkP = do
         bulletP
         texts <- (`sepBy1` try (eol >> notFollowedBy bulletP)) $ do
-            chars <- many $ noneOf "\n"
+            chars <- many $ noneOf ['\n']
             return $ T.pack chars
         let texts' = texts :: [T.Text]
         return $ T.strip $ T.intercalate (T.singleton '\n') texts'
diff --git a/src/Checkmate/Parser/IndentBlock.hs b/src/Checkmate/Parser/IndentBlock.hs
--- a/src/Checkmate/Parser/IndentBlock.hs
+++ b/src/Checkmate/Parser/IndentBlock.hs
@@ -1,30 +1,34 @@
+{-# LANGUAGE OverloadedStrings #-}
 module Checkmate.Parser.IndentBlock
-    ( parser
+    ( ParseError
+    , parser
     , parseSourceCode
     , parseSourceFile
     ) where
 
 import Control.Monad
 import Data.List
+import Data.Void
 
-import Data.Range.Range
 import Data.Set
 import Data.Text
 import Data.Text.IO
-import Text.Megaparsec
-import Text.Megaparsec.Text
+import Text.Megaparsec hiding (ParseError)
+import Text.Megaparsec.Char
+import qualified Text.Megaparsec.Error as E
 
 import Checkmate.Check
+import Checkmate.Range
 
-parseSourceFile :: FilePath
-                -> IO (Either (ParseError (Token Text) Dec) Checklist)
+type Parser = Parsec Void Text
+type ParseError = E.ParseError Char Void
+
+parseSourceFile :: FilePath -> IO (Either ParseError Checklist)
 parseSourceFile filePath = do
     input <- Data.Text.IO.readFile filePath
     return $ parseSourceCode filePath input
 
-parseSourceCode :: FilePath
-                -> Text
-                -> Either (ParseError (Token Text) Dec) Checklist
+parseSourceCode :: FilePath -> Text -> Either ParseError Checklist
 parseSourceCode = parse parser 
 
 data Line = CheckComment Text | Line | EmptyLine deriving (Eq, Ord, Show)
@@ -40,43 +44,43 @@
                  ]
     return $ Data.Set.fromList checks
   where
-    mkRange :: (Int, Int) -> Range Int
+    mkRange :: (Int, Int) -> Range
     mkRange (from, to)
-     | from >= to = SingletonRange from
-     | otherwise = SpanRange from to
+     | from >= to = Range from 1
+     | otherwise = Range from (to - from + 1)
     indent :: Parser Int
     indent = choice
         [ tab >> return 8
         , char ' ' >> return 1
         ]
     someSpaces :: Parser ()
-    someSpaces = skipMany $ oneOf " \t"
+    someSpaces = skipMany $ oneOf [' ', '\t']
     checkKeyword :: Parser ()
     checkKeyword = void $ string "CHECK"
     checkThenSpaces :: Parser ()
     checkThenSpaces = do
         checkKeyword
-        (char ':' >> someSpaces) <|> skipSome (oneOf " \t")
-    lineCommentStart :: Parser String
+        (char ':' >> someSpaces) <|> skipSome (oneOf [' ', '\t'])
+    lineCommentStart :: Parser Text
     lineCommentStart = choice
-        [ do { c <- oneOf "#%'"; return [c] }
-       , string "//"
-       , string "--"
-       ]
+        [ Data.Text.singleton <$> oneOf ['#', '%']
+        , string "//"
+        , string "--"
+        ]
     lineCommentCheck :: Parser Text
     lineCommentCheck = do
         startSeq <- lineCommentStart
         someSpaces
         checkThenSpaces
-        chars <- many $ noneOf "\n"
+        chars <- many $ noneOf ['\n']
         nextLines <- many $ try $ do
             void eol
             someSpaces
             void $ string startSeq
             someSpaces
-            many $ noneOf "\n"
+            many $ noneOf ['\n']
         return $ stripEnd $ pack $ Data.List.unlines $ chars : nextLines
-    blockCommentPairs :: [(String, String)]
+    blockCommentPairs :: [(Text, Text)]
     blockCommentPairs =
         [ ("/*", "*/"), ("{-", "-}"), ("<!--", "-->"), ("<#", "#>")
         , ("%{", "%}")
@@ -84,11 +88,11 @@
     blockCommentCheck :: Int -> Parser Text
     blockCommentCheck depth =
         choice $ fmap (blockComment depth) blockCommentPairs
-    blockComment :: Int -> (String, String) -> Parser Text
+    blockComment :: Int -> (Text, Text) -> Parser Text
     blockComment depth (start, end) = do
         void $ string start
         linebreaks <- many $ try $ do
-            skipMany $ oneOf " \t\r"
+            skipMany $ oneOf [' ', '\t', '\r']
             char '\n'
         innerDepth <- many indent
         checkThenSpaces
@@ -105,7 +109,7 @@
         lineT <- choice
             [ try $ fmap CheckComment lineCommentCheck
             , try $ CheckComment <$> blockCommentCheck depth
-            , try (some (noneOf "\n") >> return Line)
+            , try (some (noneOf ['\n']) >> return Line)
             , return EmptyLine
             ]
         return (filePath, read . show . unPos $ lineNo, depth, lineT)
diff --git a/src/Checkmate/Range.hs b/src/Checkmate/Range.hs
new file mode 100644
--- /dev/null
+++ b/src/Checkmate/Range.hs
@@ -0,0 +1,11 @@
+module Checkmate.Range
+    ( Range (..)
+    , rangesOverlap
+    ) where
+
+import Text.Diff.Parse.Types
+
+rangesOverlap :: Range -> Range -> Bool
+rangesOverlap (Range aFrom aLen) (Range bFrom bLen) =
+    aFrom <= bFrom && bFrom < aFrom + aLen ||
+        bFrom <= aFrom && aFrom < bFrom + bLen
diff --git a/src/Checkmate/Renderer.hs b/src/Checkmate/Renderer.hs
--- a/src/Checkmate/Renderer.hs
+++ b/src/Checkmate/Renderer.hs
@@ -7,7 +7,7 @@
 import Data.List
 
 import Data.Set
-import Data.Text hiding (groupBy, isSuffixOf, zip)
+import Data.Text hiding (groupBy, zip)
 import System.FilePath
 
 import Checkmate.Check
diff --git a/test/Checkmate/CheckSpec.hs b/test/Checkmate/CheckSpec.hs
--- a/test/Checkmate/CheckSpec.hs
+++ b/test/Checkmate/CheckSpec.hs
@@ -1,24 +1,23 @@
 {-# LANGUAGE FlexibleInstances #-}
 module Checkmate.CheckSpec (spec) where
 
-import Data.Range.Range
 import System.FilePath
 import Test.Hspec
 
 import Checkmate.Check
+import Checkmate.Range
 
 spec :: Spec
 spec =
     describe "Scope" $ do
         let p = "foo" </> "bar"
-            r = SingletonRange 1
+            r = Range 1 1
         it "doesn't equal if two values' data constructors are different" $ do
             FileBlock p r `shouldNotBe` Directory p
             FileBlock p r `shouldNotBe` Directory (p </> "baz")
         it "doesn't equal if two FileBlocks have different scopeRange" $ do
-            FileBlock p r `shouldNotBe` FileBlock p (SingletonRange 2)
-            FileBlock p r `shouldNotBe`
-                FileBlock (p </> "baz") (SingletonRange 2)
+            FileBlock p r `shouldNotBe` FileBlock p (Range 2 1)
+            FileBlock p r `shouldNotBe` FileBlock (p </> "baz") (Range 2 1)
         it "equals if two values' scopePaths refer to the same path" $ do
             Directory p `shouldBe` Directory p
             FileBlock p r `shouldBe` FileBlock p r
diff --git a/test/Checkmate/DiffSpec.hs b/test/Checkmate/DiffSpec.hs
deleted file mode 100644
--- a/test/Checkmate/DiffSpec.hs
+++ /dev/null
@@ -1,24 +0,0 @@
-module Checkmate.DiffSpec (spec) where
-
-import Data.Range.Range as Range
-import Test.Hspec
-import Test.QuickCheck
-import Text.Diff.Parse.Types as DT
-
-import Checkmate.Diff (rangeFromDiffRange)
-
-instance Arbitrary DT.Range where
-    arbitrary = do
-        NonZero start <- arbitrary
-        NonZero lineLen <- arbitrary
-        return $ DT.Range (abs start) (abs lineLen)
-
-spec :: Spec
-spec =
-    specify "rangeFromDiffRange" $ property $ \ dr@(DT.Range start lineLen) ->
-        let r = rangeFromDiffRange dr
-        in
-            Range.inRange r start &&
-            not (Range.inRange r $ start - 1) &&
-            Range.inRange r (start + lineLen - 1) &&
-            not (Range.inRange r $ start + lineLen)
diff --git a/test/Checkmate/DiscoverSpec.hs b/test/Checkmate/DiscoverSpec.hs
--- a/test/Checkmate/DiscoverSpec.hs
+++ b/test/Checkmate/DiscoverSpec.hs
@@ -7,7 +7,6 @@
 
 import Data.ByteString
 import Data.FileEmbed
-import Data.Range.Range (Range (..))
 import Data.Text
 import System.Directory
 import System.FilePath
@@ -65,19 +64,19 @@
 pyChecklistFixture :: FilePath -> Checklist
 pyChecklistFixture d =
     [ Check { checkScope = FileBlock { scopePath = pyPath
-                                     , scopeRange = SpanRange 2 25
+                                     , scopeRange = Range 2 24
                                      }
             , checkOrderIndex = 1
             , checkText = "module-level check"
             }
     , Check { checkScope = FileBlock { scopePath = pyPath
-                                     , scopeRange = SpanRange 11 15
+                                     , scopeRange = Range 11 5
                                      }
             , checkOrderIndex = 3
             , checkText = "function-level check 2"
             }
     , Check { checkScope = FileBlock { scopePath = pyPath
-                                     , scopeRange = SpanRange 14 15
+                                     , scopeRange = Range 14 2
                                      }
             , checkOrderIndex = 4
             , checkText = "nested function-level check"
@@ -90,19 +89,19 @@
 jsChecklistFixture :: FilePath -> Checklist
 jsChecklistFixture d =
     [ Check { checkScope = FileBlock { scopePath = jsPath
-                                     , scopeRange = SpanRange 2 21
+                                     , scopeRange = Range 2 20
                                      }
             , checkOrderIndex = 1
             , checkText = "global check"
             }
     , Check { checkScope = FileBlock { scopePath = jsPath
-                                     , scopeRange = SpanRange 10 20
+                                     , scopeRange = Range 10 11
                                      }
             , checkOrderIndex = 3
             , checkText = "function-level check 2"
             }
     , Check { checkScope = FileBlock { scopePath = jsPath
-                                     , scopeRange = SpanRange 13 17
+                                     , scopeRange = Range 13 5
                                      }
             , checkOrderIndex = 4
             , checkText = "closure check.\nIt can be multiline."
@@ -112,9 +111,12 @@
     jsPath :: FilePath
     jsPath = d </> "subdir" </> "inner_sample.js"
 
+withTempDir :: (FilePath -> IO a) -> IO a
+withTempDir = withSystemTempDirectory "checkmate-test"
+
 withFixtureDir :: (FilePath -> IO a) -> IO a
 withFixtureDir action =
-    withSystemTempDirectory "checkmate-test" $ \ dirPath -> do
+    withTempDir $ \ dirPath -> do
         forM_ fixtures $ \ (filePath, contents) -> do
             let path = dirPath </> filePath
                 parent = takeDirectory path
@@ -125,22 +127,39 @@
 
 spec :: Spec
 spec = do
-    specify "discover" $
-        withFixtureDir $ \ dirPath -> do
-            checklist <- discover dirPath diffFixture
-            let expected = subdirChecklistFixture dirPath
-                    `union` pyChecklistFixture dirPath
-                    `union` jsChecklistFixture dirPath
-            checklist `shouldBe` expected
-    specify "discoverDirectory" $
-        withFixtureDir $ \ dirPath -> do
-            subdirChecks <- discoverDirectory dirPath "subdir"
-            subdirChecks `shouldBe` subdirChecklistFixture dirPath
-            rootChecks <- discoverDirectory dirPath "."
-            rootChecks `shouldBe` rootChecklistFixture dirPath
-    specify "discoverFile" $
-        withFixtureDir $ \ dirPath -> do
-            pyChecks <- discoverFile dirPath $ Prelude.head diffFixture
-            pyChecks `shouldBe` pyChecklistFixture dirPath
-            jsChecks <- discoverFile dirPath $ Prelude.last diffFixture
-            jsChecks `shouldBe` jsChecklistFixture dirPath
+    describe "discover" $ do
+        it "scans all relative checks" $
+            withFixtureDir $ \ dirPath -> do
+                checklist <- discover dirPath diffFixture
+                let expected = subdirChecklistFixture dirPath
+                        `union` pyChecklistFixture dirPath
+                        `union` jsChecklistFixture dirPath
+                checklist `shouldBe` expected
+        it "ignores files/directories that do not exist" $
+            withTempDir $ \ dirPath -> do
+                checklist <- discover dirPath diffFixture
+                checklist `shouldBe` []
+    describe "discoverDirectory" $ do
+        it "lists files in the given path" $
+            withFixtureDir $ \ dirPath -> do
+                subdirChecks <- discoverDirectory dirPath "subdir"
+                subdirChecks `shouldBe` subdirChecklistFixture dirPath
+                rootChecks <- discoverDirectory dirPath "."
+                rootChecks `shouldBe` rootChecklistFixture dirPath
+        it "ignores files/directories that do not exist" $
+            withTempDir $ \ dirPath -> do
+                checks <- discoverDirectory
+                    (dirPath </> "dir-do-not-exist")
+                    "dir-do-not-exist"
+                checks `shouldBe` []
+    describe "discoverFile" $ do
+        it "scans all relative checks" $
+            withFixtureDir $ \ dirPath -> do
+                pyChecks <- discoverFile dirPath $ Prelude.head diffFixture
+                pyChecks `shouldBe` pyChecklistFixture dirPath
+                jsChecks <- discoverFile dirPath $ Prelude.last diffFixture
+                jsChecks `shouldBe` jsChecklistFixture dirPath
+        it "ignores files/directories that do not exist" $
+            withTempDir $ \ dirPath -> do
+                checklist <- discoverFile dirPath $ Prelude.head diffFixture
+                checklist `shouldBe` []
diff --git a/test/Checkmate/Parser/CheckFileSpec.hs b/test/Checkmate/Parser/CheckFileSpec.hs
--- a/test/Checkmate/Parser/CheckFileSpec.hs
+++ b/test/Checkmate/Parser/CheckFileSpec.hs
@@ -11,7 +11,7 @@
 import Test.Hspec
 import Test.Hspec.Megaparsec
 import Text.InterpolatedString.Perl6
-import Text.Megaparsec
+import Text.Megaparsec hiding (ParseError)
 import System.FilePath
 import System.IO.Temp
 
@@ -32,9 +32,7 @@
             return (takeDirectory filePath, result)
 
 parserSpec :: String
-           -> ( Text -> IO ( FilePath
-                           , Either (ParseError (Token Text) Dec) Checklist
-                           )
+           -> ( Text -> IO (FilePath, Either ParseError Checklist)
               )
            -> Spec
 parserSpec specName parseFn =
@@ -98,9 +96,7 @@
                 , Check dir 7 "d"
                 ]
   where
-    parse' :: Text -> IO ( Scope
-                         , Either (ParseError (Token Text) Dec) Checklist
-                         )
+    parse' :: Text -> IO (Scope, Either ParseError Checklist)
     parse' text = do
         (dir, result) <- parseFn text
         return (Directory dir, result)
diff --git a/test/Checkmate/Parser/IndentBlockSpec.hs b/test/Checkmate/Parser/IndentBlockSpec.hs
--- a/test/Checkmate/Parser/IndentBlockSpec.hs
+++ b/test/Checkmate/Parser/IndentBlockSpec.hs
@@ -7,17 +7,17 @@
 import System.IO (hClose)
 
 import Data.FileEmbed
-import Data.Range.Range
 import Data.Text
 import Data.Text.IO
 import Text.InterpolatedString.Perl6
 import Test.Hspec
 import Test.Hspec.Megaparsec
-import Text.Megaparsec
+import Text.Megaparsec hiding (ParseError)
 import System.IO.Temp
 
 import Checkmate.Check
 import Checkmate.Parser.IndentBlock
+import Checkmate.Range
 
 pythonFixture :: Text
 pythonFixture = $(embedStringFile "test/fixtures/sample.py")
@@ -47,14 +47,13 @@
     return true;
 |]
         parsed `shouldParse`
-            [ Check (FileBlock "a.js" $ SpanRange 3 8) 1
+            [ Check (FileBlock "a.js" $ Range 3 6) 1
                     "multiline\ntest\ntest2"
             ]
 
-parserSpec
-    :: String
-    -> (Text -> IO (FilePath, Either (ParseError (Token Text) Dec) Checklist))
-    -> Spec
+parserSpec :: String
+           -> (Text -> IO (FilePath, Either ParseError Checklist))
+           -> Spec
 parserSpec specName parse' = describe specName $ do
     it "returns an empty set if a given text is empty" $ do
         (_, parsed) <- parse' ""
@@ -63,11 +62,11 @@
         (path, parsed) <- parse' pythonFixture
         let s = FileBlock path
         parsed `shouldParse`
-            [ Check (s $ SpanRange 2 25) 1 "module-level check"
-            , Check (s $ SpanRange 6 7) 2 "function-level check"
-            , Check (s $ SpanRange 11 15) 3 "function-level check 2"
-            , Check (s $ SpanRange 14 15) 4 "nested function-level check"
-            , Check (s $ SpanRange 19 25) 5 "class-level check"
-            , Check (s $ SpanRange 23 25) 6
+            [ Check (s $ Range 2 24) 1 "module-level check"
+            , Check (s $ Range 6 2) 2 "function-level check"
+            , Check (s $ Range 11 5) 3 "function-level check 2"
+            , Check (s $ Range 14 2) 4 "nested function-level check"
+            , Check (s $ Range 19 7) 5 "class-level check"
+            , Check (s $ Range 23 3) 6
                     "method-level check.\nIt can be multiline."
             ]
diff --git a/test/Checkmate/RangeSpec.hs b/test/Checkmate/RangeSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Checkmate/RangeSpec.hs
@@ -0,0 +1,13 @@
+module Checkmate.RangeSpec where
+
+import Test.Hspec
+
+import Checkmate.Range
+
+spec :: Spec
+spec =
+    specify "rangesOverlap" $ do
+        Range 7 10 `shouldSatisfy` rangesOverlap (Range 5 5)
+        Range 5 5 `shouldSatisfy` rangesOverlap (Range 7 10)
+        Range 3 3 `shouldNotSatisfy` rangesOverlap (Range 7 10)
+        Range 7 10 `shouldNotSatisfy` rangesOverlap (Range 3 3)
diff --git a/test/Checkmate/RendererSpec.hs b/test/Checkmate/RendererSpec.hs
--- a/test/Checkmate/RendererSpec.hs
+++ b/test/Checkmate/RendererSpec.hs
@@ -3,13 +3,13 @@
 {-# LANGUAGE QuasiQuotes #-}
 module Checkmate.RendererSpec where
 
-import Data.Range.Range
 import Data.Text
 import System.FilePath
 import Test.Hspec
 import Text.InterpolatedString.Perl6
 
 import Checkmate.Check
+import Checkmate.Range
 import Checkmate.Renderer
 
 fixture :: Checklist
@@ -20,9 +20,9 @@
             "consectetur adipiscing elit,"
     , Check (Directory $ "b" </> "foo" </> "bar" </> ".") 3
             "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
-    , Check (FileBlock ("b" </> "foo" </> "bar" </> "baz.c") $ SpanRange 8 21) 1
+    , Check (FileBlock ("b" </> "foo" </> "bar" </> "baz.c") $ Range 8 21) 1
             "Ut enim ad minim veniam,"
-    , Check (FileBlock ("b" </> "foo" </> "bar" </> "baz.c") $ SpanRange 9 21)
+    , Check (FileBlock ("b" </> "foo" </> "bar" </> "baz.c") $ Range 9 21)
             2 $
             "quis nostrud exercitation ullamco laboris nisi ut\n" `append`
             "aliquip ex ea commodo consequat."
diff --git a/test/HLint.hs b/test/HLint.hs
deleted file mode 100644
--- a/test/HLint.hs
+++ /dev/null
@@ -1,12 +0,0 @@
-import Language.Haskell.HLint
-import System.Exit
-
-arguments :: [String]
-arguments = ["app", "src", "test"]
-
-main :: IO ()
-main = do
-    hlints <- hlint arguments
-    case hlints of
-        [] -> exitSuccess
-        _ -> exitFailure
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
diff --git a/test/Spec.hs b/test/Spec.hs
deleted file mode 100644
--- a/test/Spec.hs
+++ /dev/null
@@ -1,1 +0,0 @@
-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
