diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -17,7 +17,7 @@
 import Development.GitRev (gitDescribe)
 import GHC.Generics
 import Options.Applicative hiding (ParseError)
-import Paths_hadolint (version) -- version from hadolint.cabal file
+import qualified Paths_hadolint as Version -- version from hadolint.cabal file
 import System.Directory
        (XdgDirectory(..), doesFileExist, getCurrentDirectory,
         getXdgDirectory)
@@ -145,18 +145,18 @@
 parseFilename s = s
 
 lintDockerfile :: [IgnoreRule] -> String -> IO (Either ParseError [RuleCheck])
-lintDockerfile ignoreRules dockerfile = do
-    ast <- parseFile $ parseFilename dockerfile
+lintDockerfile ignoreRules dockerFile = do
+    ast <- parseFile $ parseFilename dockerFile
     return (processedFile ast)
   where
     processedFile = fmap processRules
-    processRules dockerfile = filter ignored (analyzeAll dockerfile)
-    ignored = ignoreFilter ignoreRules
+    processRules fileLines = filter ignoredRules (analyzeAll fileLines)
+    ignoredRules = ignoreFilter ignoreRules
 
 getVersion :: String
 getVersion
     | $(gitDescribe) == "UNKNOWN" =
-        "Haskell Dockerfile Linter " ++ V.showVersion version ++ "-no-git"
+        "Haskell Dockerfile Linter " ++ V.showVersion Version.version ++ "-no-git"
     | otherwise = "Haskell Dockerfile Linter " ++ $(gitDescribe)
 
 lint :: LintOptions -> IO ()
@@ -185,5 +185,5 @@
 
 -- Helper to analyze AST quickly in GHCI
 analyzeEither :: Either t Dockerfile -> [RuleCheck]
-analyzeEither (Left err) = []
-analyzeEither (Right dockerfile) = analyzeAll dockerfile
+analyzeEither (Left _) = []
+analyzeEither (Right dockerFile) = analyzeAll dockerFile
diff --git a/hadolint.cabal b/hadolint.cabal
--- a/hadolint.cabal
+++ b/hadolint.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: f7ed30bdbbcff79f1034336129985743db40eb1859e0c84f7567b0978c70e535
+-- hash: b523045510203dbac76d6488afec9838250f551597ef35d8b888adcbdc39e619
 
 name:           hadolint
-version:        1.6.4
+version:        1.6.5
 synopsis:       Dockerfile Linter JavaScript API
 description:    A smarter Dockerfile linter that helps you build best practice Docker images.
 category:       Development
@@ -28,13 +28,14 @@
 library
   hs-source-dirs:
       src
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints
   build-depends:
       ShellCheck >=0.4.7
     , aeson
     , base >=4.8 && <5
     , bytestring
     , dlist
-    , language-docker >=3.0.0
+    , language-docker >=5.0.0 && <6
     , parsec >=3.1
     , split >=0.2
     , text
@@ -54,13 +55,14 @@
   main-is: Main.hs
   hs-source-dirs:
       app
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints
   build-depends:
       base >=4.8 && <5
     , directory >=1.3.0
     , filepath
     , gitrev >=1.3.1
     , hadolint
-    , language-docker >=3.0.0
+    , language-docker >=5.0.0 && <6
     , optparse-applicative
     , parsec >=3.1
     , yaml
@@ -75,6 +77,7 @@
   main-is: Spec.hs
   hs-source-dirs:
       test
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints
   build-depends:
       HUnit >=1.2
     , ShellCheck >=0.4.7
@@ -83,7 +86,7 @@
     , bytestring >=0.10
     , hadolint
     , hspec
-    , language-docker >=3.0.0
+    , language-docker >=5.0.0 && <6
     , parsec >=3.1
     , split >=0.2
   other-modules:
diff --git a/src/Hadolint/Formatter/Checkstyle.hs b/src/Hadolint/Formatter/Checkstyle.hs
--- a/src/Hadolint/Formatter/Checkstyle.hs
+++ b/src/Hadolint/Formatter/Checkstyle.hs
@@ -16,7 +16,7 @@
 import Hadolint.Rules (Metadata(..), RuleCheck(..))
 import ShellCheck.Interface
 import Text.Parsec (ParseError)
-import Text.Parsec.Error (ParseError, errorPos)
+import Text.Parsec.Error (errorPos)
 import Text.Parsec.Pos
 
 data CheckStyle = CheckStyle
@@ -64,12 +64,15 @@
         attr "message" msg <>
         attr "source" source <>
         "/>"
-    fileName = case checks of
-      [] -> ""
-      h:_ -> file h
+    fileName =
+        case checks of
+            [] -> ""
+            h:_ -> file h
 
+attr :: String -> String -> Builder.Builder
 attr name value = Builder.string8 name <> "='" <> Builder.string8 (escape value) <> "' "
 
+escape :: String -> String
 escape = concatMap doEscape
   where
     doEscape c =
diff --git a/src/Hadolint/Formatter/Codeclimate.hs b/src/Hadolint/Formatter/Codeclimate.hs
--- a/src/Hadolint/Formatter/Codeclimate.hs
+++ b/src/Hadolint/Formatter/Codeclimate.hs
@@ -15,7 +15,7 @@
 import Hadolint.Formatter.Format (Result(..), formatErrorReason)
 import Hadolint.Rules (Metadata(..), RuleCheck(..))
 import ShellCheck.Interface
-import Text.Parsec.Error (errorPos)
+import Text.Parsec.Error (ParseError, errorPos)
 import Text.Parsec.Pos
 
 data Issue = Issue
@@ -54,16 +54,21 @@
             , "severity" .= impact
             ]
 
+errorToIssue :: ParseError -> Issue
 errorToIssue err =
     Issue
     { checkName = "DL1000"
     , description = formatErrorReason err
-    , location = LocPos (sourceName pos) (Pos (sourceLine pos) (sourceColumn pos))
+    , location = LocPos (sourceName pos) Pos{..}
     , impact = severityText ErrorC
     }
   where
     pos = errorPos err
+    line = sourceLine pos
+    column = sourceColumn pos
 
+
+checkToIssue :: RuleCheck -> Issue
 checkToIssue RuleCheck {..} =
     Issue
     { checkName = code metadata
diff --git a/src/Hadolint/Formatter/Format.hs b/src/Hadolint/Formatter/Format.hs
--- a/src/Hadolint/Formatter/Format.hs
+++ b/src/Hadolint/Formatter/Format.hs
@@ -8,7 +8,8 @@
 
 import Data.DList (DList, fromList, singleton)
 import Data.List (sort)
-import Data.Monoid
+import Data.Monoid (Monoid)
+import Data.Semigroup
 import Hadolint.Rules
 import ShellCheck.Interface
 import Text.Parsec.Error
@@ -19,9 +20,12 @@
     , checks :: DList RuleCheck
     } deriving (Eq)
 
+instance Semigroup Result where
+    (Result e1 c1) <> (Result e2 c2) = Result (e1 <> e2) (c1 <> c2)
+
 instance Monoid Result where
+    mappend = (<>)
     mempty = Result mempty mempty
-    mappend (Result e1 c1) (Result e2 c2) = Result (e1 <> e2) (c1 <> c2)
 
 toResult :: Either ParseError [RuleCheck] -> Result
 toResult res =
@@ -30,8 +34,8 @@
         Right c -> Result mempty (fromList (sort c))
 
 severityText :: Severity -> String
-severityText severity =
-    case severity of
+severityText s =
+    case s of
         ErrorC -> "error"
         WarningC -> "warning"
         InfoC -> "info"
diff --git a/src/Hadolint/Formatter/Json.hs b/src/Hadolint/Formatter/Json.hs
--- a/src/Hadolint/Formatter/Json.hs
+++ b/src/Hadolint/Formatter/Json.hs
@@ -14,7 +14,7 @@
 import Hadolint.Rules (Metadata(..), RuleCheck(..))
 import ShellCheck.Interface
 import Text.Parsec (ParseError)
-import Text.Parsec.Error (ParseError, errorPos)
+import Text.Parsec.Error (errorPos)
 import Text.Parsec.Pos
 
 data JsonFormat
diff --git a/src/Hadolint/Formatter/TTY.hs b/src/Hadolint/Formatter/TTY.hs
--- a/src/Hadolint/Formatter/TTY.hs
+++ b/src/Hadolint/Formatter/TTY.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NamedFieldPuns #-}
 module Hadolint.Formatter.TTY
     ( printResult
     , formatError
@@ -21,17 +22,17 @@
 formatChecks :: Functor t => t RuleCheck -> t String
 formatChecks = fmap formatCheck
   where
-    formatCheck (RuleCheck metadata source linenumber _) =
-        formatPos source linenumber ++ code metadata ++ " " ++ message metadata
+    formatCheck (RuleCheck meta source line _) =
+        formatPos source line ++ code meta ++ " " ++ message meta
 
 formatPos :: Filename -> Linenumber -> String
-formatPos source linenumber =
-    if linenumber >= 0
-        then source ++ ":" ++ show linenumber ++ " "
+formatPos source line =
+    if line >= 0
+        then source ++ ":" ++ show line ++ " "
         else source ++ " "
 
 printResult :: Result -> IO ()
-printResult (Result errors checks) = printErrors >> printChecks
+printResult Result{errors, checks} = printErrors >> printChecks
   where
     printErrors = mapM_ putStrLn (formatErrors errors)
     printChecks = mapM_ putStrLn (formatChecks checks)
diff --git a/src/Hadolint/Rules.hs b/src/Hadolint/Rules.hs
--- a/src/Hadolint/Rules.hs
+++ b/src/Hadolint/Rules.hs
@@ -92,7 +92,7 @@
 
 -- Enforce rules on a dockerfile and return failed checks
 analyze :: [Rule] -> Dockerfile -> [RuleCheck]
-analyze rules dockerfile = filter failed $ concat [r dockerfile | r <- rules]
+analyze list dockerfile = filter failed $ concat [r dockerfile | r <- list]
   where
     failed RuleCheck {metadata = Metadata {code}, linenumber, success} =
         not success && not (wasIgnored code linenumber)
@@ -119,6 +119,7 @@
     space = Parsec.char ' ' <|> Parsec.char '\t'
     ruleName = Parsec.many1 (Parsec.choice $ map Parsec.char "DLSC0123456789")
 
+rules :: [Rule]
 rules =
     [ absoluteWorkdir
     , shellcheckBash
@@ -212,6 +213,7 @@
 fromAlias (TaggedImage _ _ alias) = alias
 fromAlias (DigestedImage _ _ alias) = alias
 
+absoluteWorkdir :: Rule
 absoluteWorkdir = instructionRule code severity message check
   where
     code = "DL3000"
@@ -222,6 +224,7 @@
     check (Workdir _) = False
     check _ = True
 
+hasNoMaintainer :: Rule
 hasNoMaintainer = dockerfileRule code severity message check
   where
     code = "DL4000"
@@ -232,8 +235,10 @@
     isMaintainer _ = False
 
 -- Check if a command contains a program call in the Run instruction
+usingProgram :: String -> [String] -> Bool
 usingProgram prog args = or [True | cmd:_ <- bashCommands args, cmd == prog]
 
+multipleCmds :: Rule
 multipleCmds = dockerfileRule code severity message check
   where
     code = "DL4003"
@@ -245,6 +250,7 @@
     isCmd (Cmd _) = True
     isCmd _ = False
 
+multipleEntrypoints :: Rule
 multipleEntrypoints = dockerfileRule code severity message check
   where
     code = "DL4004"
@@ -256,6 +262,7 @@
     isEntrypoint (Entrypoint _) = True
     isEntrypoint _ = False
 
+wgetOrCurl :: Rule
 wgetOrCurl = dockerfileRule code severity message check
   where
     code = "DL4001"
@@ -267,6 +274,7 @@
     usingCmd cmd (Run (Arguments args)) = cmd `elem` args
     usingCmd _ _ = False
 
+invalidCmd :: Rule
 invalidCmd = instructionRule code severity message check
   where
     code = "DL3001"
@@ -278,6 +286,7 @@
     check _ = True
     invalidCmds = ["ssh", "vim", "shutdown", "service", "ps", "free", "top", "kill", "mount"]
 
+noRootUser :: Rule
 noRootUser = instructionRule code severity message check
   where
     code = "DL3002"
@@ -287,6 +296,7 @@
         not (isPrefixOf "root:" user || isPrefixOf "0:" user || user == "root" || user == "0")
     check _ = True
 
+noCd :: Rule
 noCd = instructionRule code severity message check
   where
     code = "DL3003"
@@ -295,6 +305,7 @@
     check (Run (Arguments args)) = not $ usingProgram "cd" args
     check _ = True
 
+noSudo :: Rule
 noSudo = instructionRule code severity message check
   where
     code = "DL3004"
@@ -305,6 +316,7 @@
     check (Run (Arguments args)) = not $ usingProgram "sudo" args
     check _ = True
 
+noAptGetUpgrade :: Rule
 noAptGetUpgrade = instructionRule code severity message check
   where
     code = "DL3005"
@@ -313,16 +325,18 @@
     check (Run (Arguments args)) = not $ isInfixOf ["apt-get", "upgrade"] args
     check _ = True
 
+noUntagged :: Rule
 noUntagged dockerfile = instructionRuleLine code severity message check dockerfile
   where
     code = "DL3006"
     severity = WarningC
     message = "Always tag the version of an image explicitly"
-    check line (From (UntaggedImage (Image _ "scratch") _)) = True
+    check _ (From (UntaggedImage (Image _ "scratch") _)) = True
     check line (From (UntaggedImage (Image _ i) _)) =
         i `elem` previouslyDefinedAliases line dockerfile
     check _ _ = True
 
+noLatestTag :: Rule
 noLatestTag = instructionRule code severity message check
   where
     code = "DL3007"
@@ -333,6 +347,7 @@
     check (From (TaggedImage _ tag _)) = tag /= "latest"
     check _ = True
 
+aptGetVersionPinned :: Rule
 aptGetVersionPinned = instructionRule code severity message check
   where
     code = "DL3008"
@@ -354,6 +369,7 @@
   where
     noOption arg = arg `notElem` ["apt-get", "install"] && not ("-" `isPrefixOf` arg)
 
+aptGetCleanup :: Rule
 aptGetCleanup dockerfile = instructionRuleState code severity message check Nothing dockerfile
   where
     code = "DL3009"
@@ -384,11 +400,12 @@
                 alias `elem` [i | (l, i) <- allImageNames dockerfile, l > line]
 
 dropOptionsWithArg :: [String] -> [String] -> [String]
-dropOptionsWithArg os [] = []
+dropOptionsWithArg _ [] = []
 dropOptionsWithArg os (x:xs)
     | x `elem` os = dropOptionsWithArg os (drop 1 xs)
     | otherwise = x : dropOptionsWithArg os xs
 
+noApkUpgrade :: Rule
 noApkUpgrade = instructionRule code severity message check
   where
     code = "DL3017"
@@ -400,6 +417,7 @@
 isApkAdd :: [String] -> Bool
 isApkAdd cmd = ["apk"] `isInfixOf` cmd && ["add"] `isInfixOf` cmd
 
+apkAddVersionPinned :: Rule
 apkAddVersionPinned = instructionRule code severity message check
   where
     code = "DL3018"
@@ -421,6 +439,7 @@
     noOption arg = arg `notElem` options && not ("--" `isPrefixOf` arg)
     options = ["apk", "add", "-q", "-p", "-v", "-f", "-t"]
 
+apkAddNoCache :: Rule
 apkAddNoCache = instructionRule code severity message check
   where
     code = "DL3019"
@@ -432,6 +451,7 @@
     check _ = True
     hasNoCacheOption cmd = ["--no-cache"] `isInfixOf` cmd
 
+useAdd :: Rule
 useAdd = instructionRule code severity message check
   where
     code = "DL3010"
@@ -446,6 +466,7 @@
     check _ = True
     archiveFormats = [".tar", ".gz", ".bz2", "xz"]
 
+invalidPort :: Rule
 invalidPort = instructionRule code severity message check
   where
     code = "DL3011"
@@ -453,9 +474,10 @@
     message = "Valid UNIX ports range from 0 to 65535"
     check (Expose (Ports ports)) =
         and [p <= 65535 | Port p _ <- ports] &&
-        and [l <= 65535 && m <= 65535 | PortRange l m <- ports]
+        and [l <= 65535 && m <= 65535 | PortRange l m _ <- ports]
     check _ = True
 
+pipVersionPinned :: Rule
 pipVersionPinned = instructionRule code severity message check
   where
     code = "DL3013"
@@ -513,6 +535,7 @@
     npm install git[+http|+https]://<git-host>/<git-user>/<repo-name>[#<commit>|#semver:<semver>]
     npm install git+ssh://<git-host>:<git-user>/<repo-name>[#<commit>|#semver:<semver>]
 -}
+npmVersionPinned :: Rule
 npmVersionPinned = instructionRule code severity message check
   where
     code = "DL3016"
@@ -536,13 +559,15 @@
     isVersionedGit package = "#" `isInfixOf` package
     hasVersionSymbol package = "@" `isInfixOf` dropScope package
       where
-        dropScope package =
-            if "@" `isPrefixOf` package
-                then dropWhile ('/' <) package
-                else package
+        dropScope pkg =
+            if "@" `isPrefixOf` pkg
+                then dropWhile ('/' <) pkg
+                else pkg
 
+isAptGetInstall :: [String] -> Bool
 isAptGetInstall cmd = ["apt-get"] `isInfixOf` cmd && ["install"] `isInfixOf` cmd
 
+aptGetYes :: Rule
 aptGetYes = instructionRule code severity message check
   where
     code = "DL3014"
@@ -555,6 +580,7 @@
         ["--yes"] `isInfixOf` cmd || ["-qq"] `isInfixOf` cmd || startsWithYesFlag cmd
     startsWithYesFlag cmd = True `elem` ["-y" `isInfixOf` arg | arg <- cmd]
 
+aptGetNoRecommends :: Rule
 aptGetNoRecommends = instructionRule code severity message check
   where
     code = "DL3015"
@@ -590,6 +616,7 @@
 isUrl :: String -> Bool
 isUrl path = True `elem` [proto `isPrefixOf` path | proto <- ["https://", "http://"]]
 
+copyInsteadAdd :: Rule
 copyInsteadAdd = instructionRule code severity message check
   where
     code = "DL3020"
@@ -599,6 +626,7 @@
         and [isArchive src || isUrl src | SourcePath src <- toList srcs]
     check _ = True
 
+copyEndingSlash :: Rule
 copyEndingSlash = instructionRule code severity message check
   where
     code = "DL3021"
@@ -610,6 +638,7 @@
     check _ = True
     endsWithSlash (TargetPath t) = last t == '/' -- it is safe to use last, as the target is never empty
 
+copyFromExists :: Rule
 copyFromExists dockerfile = instructionRuleLine code severity message check dockerfile
   where
     code = "DL3022"
@@ -618,6 +647,7 @@
     check l (Copy (CopyArgs _ _ _ (CopySource s))) = s `elem` previouslyDefinedAliases l dockerfile
     check _ _ = True
 
+copyFromAnother :: Rule
 copyFromAnother = instructionRuleState code severity message check Nothing
   where
     code = "DL3023"
@@ -632,6 +662,7 @@
         withState st (aliasMustBe (/= stageName) fromInstr) -- Cannot copy from itself!
     check state _ _ = withState state True
 
+fromAliasUnique :: Rule
 fromAliasUnique dockerfile = instructionRuleLine code severity message check dockerfile
   where
     code = "DL3024"
@@ -640,6 +671,7 @@
     check line = aliasMustBe (not . alreadyTaken line)
     alreadyTaken line alias = alias `elem` previouslyDefinedAliases line dockerfile
 
+useShell :: Rule
 useShell = instructionRule code severity message check
   where
     code = "DL4005"
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -6,9 +6,6 @@
 
 import Language.Docker.Parser
 
-import Data.List (find)
-import Data.Maybe (fromMaybe, isJust)
-
 main :: IO ()
 main =
     hspec $ do
@@ -25,7 +22,7 @@
             it "explicit tagged with name" $
               ruleCatchesNot noLatestTag "FROM debian:jessie AS builder"
             it "local aliases are OK to be untagged" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM golang:1.9.3-alpine3.7 AS build"
                         , "RUN foo"
                         , "FROM build as unit-test"
@@ -33,9 +30,9 @@
                         , "FROM alpine:3.7"
                         , "RUN baz"
                         ]
-                in ruleCatchesNot noUntagged $ unlines dockerfile
+                in ruleCatchesNot noUntagged $ unlines dockerFile
             it "other untagged cases are not ok" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM golang:1.9.3-alpine3.7 AS build"
                         , "RUN foo"
                         , "FROM node as unit-test"
@@ -43,7 +40,7 @@
                         , "FROM alpine:3.7"
                         , "RUN baz"
                         ]
-                in ruleCatches noUntagged $ unlines dockerfile
+                in ruleCatches noUntagged $ unlines dockerFile
         --
         describe "no root or sudo rules" $ do
             it "sudo" $ ruleCatches noSudo "RUN sudo apt-get update"
@@ -65,74 +62,74 @@
             it "apt-get version pinning" $
                 ruleCatches aptGetVersionPinned "RUN apt-get update && apt-get install python"
             it "apt-get no cleanup" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM scratch"
                         , "RUN apt-get update && apt-get install python"
                         ]
-                in ruleCatches aptGetCleanup $ unlines dockerfile
+                in ruleCatches aptGetCleanup $ unlines dockerFile
             it "apt-get cleanup in stage image" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM ubuntu as foo"
                         , "RUN apt-get update && apt-get install python"
                         , "FROM scratch"
                         , "RUN echo hey!"
                         ]
-                in ruleCatchesNot aptGetCleanup $ unlines dockerfile
+                in ruleCatchesNot aptGetCleanup $ unlines dockerFile
             it "apt-get no cleanup in last stage" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM ubuntu as foo"
                         , "RUN hey!"
                         , "FROM scratch"
                         , "RUN apt-get update && apt-get install python"
                         ]
-                in ruleCatches aptGetCleanup $ unlines dockerfile
+                in ruleCatches aptGetCleanup $ unlines dockerFile
             it "apt-get no cleanup in intermediate stage" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM ubuntu as foo"
                         , "RUN apt-get update && apt-get install python"
                         , "FROM foo"
                         , "RUN hey!"
                         ]
-                in ruleCatches aptGetCleanup $ unlines dockerfile
+                in ruleCatches aptGetCleanup $ unlines dockerFile
             it "now warn apt-get cleanup in intermediate stage that cleans lists" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM ubuntu as foo"
                         , "RUN apt-get update && apt-get install python && rm -rf /var/lib/apt/lists/*"
                         , "FROM foo"
                         , "RUN hey!"
                         ]
-                in ruleCatchesNot aptGetCleanup $ unlines dockerfile
+                in ruleCatchesNot aptGetCleanup $ unlines dockerFile
             it "no warn apt-get cleanup in intermediate stage when stage not used later" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM ubuntu as foo"
                         , "RUN apt-get update && apt-get install python"
                         , "FROM scratch"
                         , "RUN hey!"
                         ]
-                in ruleCatchesNot aptGetCleanup $ unlines dockerfile
+                in ruleCatchesNot aptGetCleanup $ unlines dockerFile
             it "apt-get cleanup" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM scratch"
                         , "RUN apt-get update && apt-get install python && rm -rf /var/lib/apt/lists/*"
                         ]
-                in ruleCatchesNot aptGetCleanup $ unlines dockerfile
+                in ruleCatchesNot aptGetCleanup $ unlines dockerFile
 
             it "apt-get pinned chained" $
-                let dockerfile =
+                let dockerFile =
                         [ "RUN apt-get update \\"
                         , " && apt-get -yqq --no-install-recommends install nodejs=0.10 \\"
                         , " && rm -rf /var/lib/apt/lists/*"
                         ]
-                in ruleCatchesNot aptGetVersionPinned $ unlines dockerfile
+                in ruleCatchesNot aptGetVersionPinned $ unlines dockerFile
             it "apt-get pinned regression" $
-                let dockerfile =
+                let dockerFile =
                         [ "RUN apt-get update && apt-get install --no-install-recommends -y \\"
                         , "python-demjson=2.2.2* \\"
                         , "wget=1.16.1* \\"
                         , "git=1:2.5.0* \\"
                         , "ruby=1:2.1.*"
                         ]
-                in ruleCatchesNot aptGetVersionPinned $ unlines dockerfile
+                in ruleCatchesNot aptGetVersionPinned $ unlines dockerFile
             it "has deprecated maintainer" $
                 ruleCatches hasNoMaintainer "FROM busybox\nMAINTAINER hudu@mail.com"
         --
@@ -142,34 +139,34 @@
             it "apk add no version pinning single" $
                 ruleCatchesNot apkAddVersionPinned "RUN apk add flex=2.6.4-r1"
             it "apk add version pinned chained" $
-                let dockerfile =
+                let dockerFile =
                         [ "RUN apk add --no-cache flex=2.6.4-r1 \\"
                         , " && pip install -r requirements.txt"
                         ]
-                in ruleCatchesNot apkAddVersionPinned $ unlines dockerfile
+                in ruleCatchesNot apkAddVersionPinned $ unlines dockerFile
             it "apk add version pinned regression" $
-                let dockerfile =
+                let dockerFile =
                         [ "RUN apk add --no-cache \\"
                         , "flex=2.6.4-r1 \\"
                         , "libffi=3.2.1-r3 \\"
                         , "python2=2.7.13-r1 \\"
                         , "libbz2=1.0.6-r5"
                         ]
-                in ruleCatchesNot apkAddVersionPinned $ unlines dockerfile
+                in ruleCatchesNot apkAddVersionPinned $ unlines dockerFile
             it "apk add version pinned regression - one missed" $
-                let dockerfile =
+                let dockerFile =
                         [ "RUN apk add --no-cache \\"
                         , "flex=2.6.4-r1 \\"
                         , "libffi \\"
                         , "python2=2.7.13-r1 \\"
                         , "libbz2=1.0.6-r5"
                         ]
-                in ruleCatches apkAddVersionPinned $ unlines dockerfile
+                in ruleCatches apkAddVersionPinned $ unlines dockerFile
             it "apk add with --no-cache" $ ruleCatches apkAddNoCache "RUN apk add flex=2.6.4-r1"
             it "apk add without --no-cache" $
                 ruleCatchesNot apkAddNoCache "RUN apk add --no-cache flex=2.6.4-r1"
             it "apk add virtual package" $
-                let dockerfile =
+                let dockerFile =
                         [ "RUN apk add \\"
                         , "--virtual build-dependencies \\"
                         , "python-dev=1.1.1 build-base=2.2.2 wget=3.3.3 \\"
@@ -177,7 +174,7 @@
                         , "&& python setup.py install \\"
                         , "&& apk del build-dependencies"
                         ]
-                in ruleCatchesNot apkAddVersionPinned $ unlines dockerfile
+                in ruleCatchesNot apkAddVersionPinned $ unlines dockerFile
         --
         describe "EXPOSE rules" $ do
             it "invalid port" $ ruleCatches invalidPort "EXPOSE 80000"
@@ -311,7 +308,7 @@
                     aptGetVersionPinned
                     "RUN apt-get -y --no-install-recommends install nodejs=0.10"
             it "apt-get tolerate target-release" $
-                let dockerfile =
+                let dockerFile =
                         [ "RUN set -e &&\\"
                         , " echo \"deb http://http.debian.net/debian jessie-backports main\" \
                           \> /etc/apt/sources.list.d/jessie-backports.list &&\\"
@@ -320,7 +317,7 @@
                           \openjdk-8-jdk=8u131-b11-1~bpo8+1 &&\\"
                         , " rm -rf /var/lib/apt/lists/*"
                         ]
-                in ruleCatchesNot aptGetVersionPinned $ unlines dockerfile
+                in ruleCatchesNot aptGetVersionPinned $ unlines dockerFile
 
             it "has maintainer" $ ruleCatches hasNoMaintainer "FROM debian\nMAINTAINER Lukas"
             it "has maintainer first" $ ruleCatches hasNoMaintainer "MAINTAINER Lukas\nFROM DEBIAN"
@@ -353,57 +350,57 @@
         describe "copy from existing alias" $ do
             it "warn on missing alias" $ ruleCatches copyFromExists "COPY --from=foo bar ."
             it "warn on alias defined after" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM scratch"
                         , "COPY --from=build foo ."
                         , "FROM node as build"
                         , "RUN baz"
                         ]
-                in ruleCatches copyFromExists $ unlines dockerfile
+                in ruleCatches copyFromExists $ unlines dockerFile
             it "don't warn on correctly defined aliases" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM scratch as build"
                         , "RUN foo"
                         , "FROM node"
                         , "COPY --from=build foo ."
                         , "RUN baz"
                         ]
-                in ruleCatchesNot copyFromExists $ unlines dockerfile
+                in ruleCatchesNot copyFromExists $ unlines dockerFile
         --
         describe "copy from own FROM" $ do
             it "warn on copying from your the same FROM" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM node as foo"
                         , "COPY --from=foo bar ."
                         ]
-                in ruleCatches copyFromAnother $ unlines dockerfile
+                in ruleCatches copyFromAnother $ unlines dockerFile
             it "don't warn on copying form other sources" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM scratch as build"
                         , "RUN foo"
                         , "FROM node as run"
                         , "COPY --from=build foo ."
                         , "RUN baz"
                         ]
-                in ruleCatchesNot copyFromAnother $ unlines dockerfile
+                in ruleCatchesNot copyFromAnother $ unlines dockerFile
         --
         describe "Duplicate aliases" $ do
             it "warn on duplicate aliases" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM node as foo"
                         , "RUN something"
                         , "FROM scratch as foo"
                         , "RUN something"
                         ]
-                in ruleCatches fromAliasUnique $ unlines dockerfile
+                in ruleCatches fromAliasUnique $ unlines dockerFile
             it "don't warn on unique aliases" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM scratch as build"
                         , "RUN foo"
                         , "FROM node as run"
                         , "RUN baz"
                         ]
-                in ruleCatchesNot fromAliasUnique $ unlines dockerfile
+                in ruleCatchesNot fromAliasUnique $ unlines dockerFile
         --
         describe "format error" $
             it "display error after line pos" $ do
@@ -415,51 +412,52 @@
         --
         describe "Rules can be ignored with inline comments" $ do
             it "ignores single rule" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM ubuntu"
                         , "# hadolint ignore=DL3002"
                         , "USER root"
                         ]
-                in ruleCatchesNot noRootUser $ unlines dockerfile
+                in ruleCatchesNot noRootUser $ unlines dockerFile
             it "ignores only the given rule" $
-                let dockerfile =
+                let dockerFile =
                         [ "# hadolint ignore=DL3001"
                         , "USER root"
                         ]
-                in ruleCatches noRootUser $ unlines dockerfile
+                in ruleCatches noRootUser $ unlines dockerFile
             it "ignores only the given rule, when multiple passed" $
-                let dockerfile =
+                let dockerFile =
                         [ "# hadolint ignore=DL3001,DL3002"
                         , "USER root"
                         ]
-                in ruleCatchesNot noRootUser $ unlines dockerfile
+                in ruleCatchesNot noRootUser $ unlines dockerFile
             it "ignores the rule only if directly above the instruction" $
-                let dockerfile =
+                let dockerFile =
                         [ "# hadolint ignore=DL3001,DL3002"
                         , "FROM ubuntu"
                         , "USER root"
                         ]
-                in ruleCatches noRootUser $ unlines dockerfile
+                in ruleCatches noRootUser $ unlines dockerFile
             it "won't ignore the rule if passed invalid rule names" $
-                let dockerfile =
+                let dockerFile =
                         [ "# hadolint ignore=crazy,DL3002"
                         , "USER root"
                         ]
-                in ruleCatches noRootUser $ unlines dockerfile
+                in ruleCatches noRootUser $ unlines dockerFile
             it "ignores multiple rules correctly, even with some extra whitespace" $
-                let dockerfile =
+                let dockerFile =
                         [ "FROM node as foo"
                         , "# hadolint ignore=DL3023, DL3021"
                         , "COPY --from=foo bar baz ."
                         ]
                 in do
-                  ruleCatchesNot copyFromAnother $ unlines dockerfile
-                  ruleCatchesNot copyEndingSlash $ unlines dockerfile
+                  ruleCatchesNot copyFromAnother $ unlines dockerFile
+                  ruleCatchesNot copyEndingSlash $ unlines dockerFile
 
+assertChecks :: Rule -> String -> ([RuleCheck] -> IO a) -> IO a
 assertChecks rule s f =
     case parseString (s ++ "\n") of
         Left err -> assertFailure $ show err
-        Right dockerfile -> f $ analyze [rule] dockerfile
+        Right dockerFile -> f $ analyze [rule] dockerFile
 
 -- Assert a failed check exists for rule
 ruleCatches :: Rule -> String -> Assertion
