diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -15,8 +15,8 @@
 ```
 
 Binaries are also available:
- * [elocrypt-2.0.0-linux-bin.tar.gz](https://github.com/sgillespie/elocrypt/releases/download/v1.0.0/elocrypt-1.0.0-linux-bin.tar.gz)
- * [elocrypt-2.0.0-windows-bin.exe](https://github.com/sgillespie/elocrypt/releases/download/v1.0.0/elocrypt-1.0.0-windows-bin.exe)
+ * [elocrypt-2.0.0-linux-bin.tar.gz](https://github.com/sgillespie/elocrypt/releases/download/v2.0.0/elocrypt-2.0.0-linux-bin.tar.gz)
+ * [elocrypt-2.0.0-windows-bin.exe](https://github.com/sgillespie/elocrypt/releases/download/v2.0.0/elocrypt-2.0.0-windows-bin.exe)
 
 ## Running
 Generate a list passwords:
diff --git a/elocrypt.cabal b/elocrypt.cabal
--- a/elocrypt.cabal
+++ b/elocrypt.cabal
@@ -1,5 +1,5 @@
 name:                elocrypt
-version:             2.0.0
+version:             2.0.1
 synopsis:            Generate easy-to-remember, hard-to-guess passwords
 homepage:            https://www.github.com/sgillespie/elocrypt
 license:             OtherLicense
@@ -26,7 +26,7 @@
 source-repository this
   type: git
   location: https://github.com/sgillespie/elocrypt.git
-  tag: v1.0.0
+  tag: v2.0.1
                   
 library
   exposed-modules:     Data.Elocrypt,
diff --git a/src/cli/Main.hs b/src/cli/Main.hs
--- a/src/cli/Main.hs
+++ b/src/cli/Main.hs
@@ -12,12 +12,12 @@
 
 import Data.Elocrypt
 
-version    :: String
-termLen    :: Int
+version :: String
+termLen :: Int
 termHeight :: Int
 
-version    = "elocrypt 2.0.0"
-termLen    = 80
+version = "elocrypt 2.0.1"
+termLen = 80
 termHeight = 10
 
 data Options = Options {
@@ -36,44 +36,46 @@
   deriving (Eq, Show)
 
 defaultOptions :: Options
-defaultOptions = Options {
-      optCapitals  = False,
-      optLength    = 8,
-      optMaxLength = 10,
-      optNumber    = Nothing,
-      optPassType  = Word,
-      optHelp      = False,
-      optVersion   = False
+defaultOptions = Options
+  { optCapitals = False
+  , optLength = 8
+  , optMaxLength = 10
+  , optNumber = Nothing
+  , optPassType = Word
+  , optHelp = False
+  , optVersion = False
   }
 
 options :: [OptDescr (Options -> Options)]
-options = [
-      Option ['c'] ["capitals"] 
-        (NoArg (\o -> o { optCapitals = True }))
-        "Include capital letters",
-
-      Option ['n'] ["number"]
-        (ReqArg (\n o -> o { optNumber = Just (read n) }) "NUMBER")
-        "The number of passwords to generate",
-
-      Option ['p'] ["passphrase"]
-        (NoArg (\o -> o { optPassType = Phrase }))
-        "Generate passphrases instead of passwords",
-
-      Option ['h'] ["help"]
-        (NoArg (\o -> o { optHelp = True }))
-        "Show this help",
-
-      Option ['v'] ["version"]
-        (NoArg (\o -> o { optVersion = True }))
-        "Show version and exit"
+options =
+  [ Option
+    ['c']
+    ["capitals"]
+    (NoArg (\o -> o { optCapitals = True }))
+    "Include at least one capital letter"
+  , Option
+    ['n']
+    ["number"]
+    (ReqArg (\n o -> o { optNumber = Just (read n) }) "NUMBER")
+    "The number of passwords to generate"
+  , Option
+    ['p']
+    ["passphrase"]
+    (NoArg (\o -> o { optPassType = Phrase }))
+    "Generate passphrases instead of passwords"
+  , Option ['h'] ["help"] (NoArg (\o -> o { optHelp = True })) "Show this help"
+  , Option
+    ['v']
+    ["version"]
+    (NoArg (\o -> o { optVersion = True }))
+    "Show version and exit"
   ]
 
 main :: IO ()
 main = do
   args <- getArgs
   opts <- elocryptOpts args
-  gen  <- getStdGen
+  gen <- getStdGen
 
   when (optHelp opts) $ do
     hPutStrLn stderr usage
@@ -83,8 +85,7 @@
     hPutStrLn stderr version
     exitSuccess
 
-  when (optLength opts == 0)
-    exitSuccess    -- Nothing to do
+  when (optLength opts == 0) exitSuccess    -- Nothing to do
 
   putStrLn (generate opts gen)
 
@@ -93,9 +94,9 @@
   (opts, nonopts) <- elocryptOpts' args
 
   return $ case nonopts of
-    (o:os:_) -> opts { optLength = read o, optMaxLength = read os }
-    (o:_)    -> opts { optLength = read o }
-    []       -> opts
+    (o : os : _) -> opts { optLength = read o, optMaxLength = read os }
+    (o : _) -> opts { optLength = read o }
+    [] -> opts
 
 elocryptOpts' :: [String] -> IO (Options, [String])
 elocryptOpts' args = case getOpt Permute options args of
@@ -103,50 +104,52 @@
     let opts' = foldl (flip id) defaultOptions opts
     return (opts', nonopts)
 
-  (_   , _      , errs) -> do
+  (_, _, errs) -> do
     hPutStrLn stderr (concat errs)
     hPutStrLn stderr usage
     exitFailure
 
 generate :: RandomGen g => Options -> g -> String
-generate opts@Options{optPassType=Word}   = passwords opts
-generate opts@Options{optPassType=Phrase} = passphrases opts
+generate opts@Options { optPassType = Word } = passwords opts
+generate opts@Options { optPassType = Phrase } = passphrases opts
 
 passwords :: RandomGen g => Options -> g -> String
-passwords opts@Options{optLength = len, optNumber = n} gen
-  = format "  " . groupWith splitAt' width "  " $ ps
-  where ps = newPasswords len num (getGenOptions opts) gen
-        cols = columns len
-        num = fromMaybe (nWords cols) n
-        width = max termLen (len + 2)
+passwords opts@Options { optLength = len, optNumber = n } gen =
+  format "  " . groupWith splitAt' width "  " $ ps
+  where
+    ps = newPasswords len num (getGenOptions opts) gen
+    cols = columns len
+    num = fromMaybe (nWords cols) n
+    width = max termLen (len + 2)
 
 passphrases :: RandomGen g => Options -> g -> String
-passphrases opts@Options{optCapitals = caps,
-                    optLength = minLen,
-                    optMaxLength = maxLen,
-                    optNumber = n} gen
+passphrases opts@Options { optCapitals = caps, optLength = minLen, optMaxLength = maxLen, optNumber = n } gen
   = format " " . take lines' . groupWith splitAt' width " " $ passphrase
-  where passphrase = newPassphrase words' minLen maxLen (getGenOptions opts) gen
-        words' = columns minLen * lines'
-        width = max termLen (maxLen + 1)
-        lines' = fromMaybe termHeight n
+  where
+    passphrase = newPassphrase words' minLen maxLen (getGenOptions opts) gen
+    words' = columns minLen * lines'
+    width = max termLen (maxLen + 1)
+    lines' = fromMaybe termHeight n
 
 getGenOptions :: Options -> GenOptions
-getGenOptions Options{optCapitals=caps} = genOptions{genCapitals=caps}
+getGenOptions Options { optCapitals = caps } =
+  genOptions { genCapitals = caps }
 
 usage :: String
 usage = usageInfo (intercalate "\n" headerLines) options
-  where headerLines = [
-              "Usage: elocrypt [option...] length",
-              "       elocrypt -p [option...] min-length max-length"
-          ]
+  where
+    headerLines =
+      [ "Usage: elocrypt [option...] length"
+      , "       elocrypt -p [option...] min-length max-length"
+      ]
 
 -- Utilities
 
 -- Calculate the number of passwords to print per line
 columns :: Int -> Int
-columns len | len <= termLen - 2 = termLen `div` (len + 2)
-            | otherwise = 1
+columns len
+  | len <= termLen - 2 = termLen `div` (len + 2)
+  | otherwise = 1
 
 -- Format a 2D list of Strings,
 --  1 list per line
@@ -159,31 +162,25 @@
 
 -- Group a 2D array with a function by total length
 groupWith
-  :: (Int -> [a] -> [[a]] -> ([[a]], [[a]]))
-  -> Int
-  -> [a]
-  -> [[a]]
-  -> [[[a]]]
+  :: (Int -> [a] -> [[a]] -> ([[a]], [[a]])) -> Int -> [a] -> [[a]] -> [[[a]]]
 groupWith _ _ _ [] = []
-groupWith f i sep ls | null groups = [[head ls]]
-                     | otherwise = groups
+groupWith f i sep ls
+  | null groups = [[head ls]]
+  | otherwise = groups
   where groups = groupWith' f i sep ls
 
 groupWith'
-  :: (Int -> [a] -> [[a]] -> ([[a]], [[a]]))
-  -> Int
-  -> [a]
-  -> [[a]]
-  -> [[[a]]]
+  :: (Int -> [a] -> [[a]] -> ([[a]], [[a]])) -> Int -> [a] -> [[a]] -> [[[a]]]
 groupWith' _ _ _ [] = []
-groupWith' f i sep ls = g : groupWith f i sep ls'
-  where (g, ls') = f i sep ls
+groupWith' f i sep ls = g : groupWith f i sep ls' where (g, ls') = f i sep ls
 
 -- Split a 2D array by the total length
 splitAt' :: Int -> [a] -> [[a]] -> ([[a]], [[a]])
 splitAt' 0 _ ls = ([], ls)
 splitAt' _ _ [] = ([], [])
-splitAt' n sep (l:ls) | n >= length l + sl = (l:xs, xs')
-                      | otherwise = ([], l:ls)
-  where (xs, xs') = splitAt' (n - length l - sl) sep ls
-        sl = length sep
+splitAt' n sep (l : ls)
+  | n >= length l + sl = (l : xs, xs')
+  | otherwise = ([], l : ls)
+  where
+    (xs, xs') = splitAt' (n - length l - sl) sep ls
+    sl = length sep
diff --git a/src/lib/Data/Elocrypt.hs b/src/lib/Data/Elocrypt.hs
--- a/src/lib/Data/Elocrypt.hs
+++ b/src/lib/Data/Elocrypt.hs
@@ -31,9 +31,7 @@
 -- |Default options for generating passwords or passphrases. This is
 -- the preferred way to construct 'GenOptions'.
 genOptions :: GenOptions
-genOptions = GenOptions {
-  genCapitals = False
-}
+genOptions = GenOptions {genCapitals = False}
 
 -- * Random password generators
 
@@ -45,11 +43,12 @@
 --  myGenPassword :: IO (String, StdGen)
 --  myGenPassword = genPassword 10 genOptions \`liftM\` getStdGen
 --  @
-genPassword :: RandomGen g
-               => Int        -- ^ password length
-               -> GenOptions -- ^ options
-               -> g          -- ^ random generator
-               -> (String, g)
+genPassword
+  :: RandomGen g
+  => Int        -- ^ password length
+  -> GenOptions -- ^ options
+  -> g          -- ^ random generator
+  -> (String, g)
 genPassword len = runRand . mkPassword len
 
 -- |Plural version of genPassword.  Generates an infinite list of passwords
@@ -60,12 +59,13 @@
 -- myGenPasswords :: IO ([String], StdGen)
 -- myGenPasswords = (\(ls, g) -> (ls, g) `liftM` genPasswords 10 10 genOptions `liftM` getStdGen
 -- @
-genPasswords :: RandomGen g
-                => Int        -- ^ password length
-                -> Int        -- ^ number of passwords
-                -> GenOptions -- ^ options
-                -> g          -- ^ random generator
-                -> ([String], g)
+genPasswords
+  :: RandomGen g
+  => Int        -- ^ password length
+  -> Int        -- ^ number of passwords
+  -> GenOptions -- ^ options
+  -> g          -- ^ random generator
+  -> ([String], g)
 genPasswords len n = runRand . mkPasswords len n
 
 -- |Generate a password using the generator g, returning the result.
@@ -75,11 +75,12 @@
 --  myNewPassword :: IO String
 --  myNewPassword = newPassword 10 genOptions \`liftM\` getStdGen
 --  @
-newPassword :: RandomGen g
-               => Int        -- ^ password length
-               -> GenOptions -- ^ options
-               -> g          -- ^ random generator
-               -> String
+newPassword
+  :: RandomGen g
+  => Int        -- ^ password length
+  -> GenOptions -- ^ options
+  -> g          -- ^ random generator
+  -> String
 newPassword len = evalRand . mkPassword len
 
 -- |Plural version of newPassword.  Generates an infinite list of passwords
@@ -90,12 +91,13 @@
 -- myNewPasswords :: IO [String]
 -- myNewPasswords = genPasswords 10 10 genOptions `liftM` getStdGen
 -- @
-newPasswords :: RandomGen g
-                => Int        -- ^ password length
-                -> Int        -- ^ number of passwords
-                -> GenOptions -- ^ options
-                -> g          -- ^ random generator
-                -> [String]
+newPasswords
+  :: RandomGen g
+  => Int        -- ^ password length
+  -> Int        -- ^ number of passwords
+  -> GenOptions -- ^ options
+  -> g          -- ^ random generator
+  -> [String]
 newPasswords len n = evalRand . mkPasswords len n
 
 -- |Generate a password using the MonadRandom m. MonadRandom is exposed here
@@ -106,16 +108,20 @@
 --  myPassword :: IO String
 --  myPassword = evalRand (mkPassword 10 genOptions) \`liftM\` getStdGen
 --  @
-mkPassword :: MonadRandom m
-              => Int        -- ^ password length
-              -> GenOptions -- ^ options
-              -> m String
+mkPassword
+  :: MonadRandom m
+  => Int        -- ^ password length
+  -> GenOptions -- ^ options
+  -> m String
 mkPassword len opts = do
-  f2 <- reverse `liftM` first2 opts
-  if len > 2
-    then reverse `liftM` lastN opts (len - 2) f2
-    else return . reverse . take len $ f2
+  f2 <- first2
+  let f2' = reverse f2
 
+  pass <- if len > 2 then lastN (len - 2) f2' else return (take len f2')
+  let pass' = reverse pass
+
+  if genCapitals opts then capitalizeR len pass' else return pass'
+
 -- |Plural version of mkPassword.  Generate an infinite list of passwords using
 --  the MonadRandom m.  MonadRandom is exposed here for extra control.
 --
@@ -124,11 +130,12 @@
 -- myMkPasswords :: IO [String]
 -- myMkPasswords = evalRand (mkPasswords 10 20 genOptions) \`liftM\` getStdGen
 -- @
-mkPasswords :: MonadRandom m
-               => Int        -- ^ password length
-               -> Int        -- ^ number of passwords
-               -> GenOptions -- ^ options
-               -> m [String]
+mkPasswords
+  :: MonadRandom m
+  => Int        -- ^ password length
+  -> Int        -- ^ number of passwords
+  -> GenOptions -- ^ options
+  -> m [String]
 mkPasswords len n = replicateM n . mkPassword len
 
 -- * Random passphrase generators
@@ -142,13 +149,14 @@
 --  myGenPassphrase :: IO (String, StdGen)
 --  myGenPassphrase = genPassword 10 6 10 genOptions \`liftM\` getStdGen
 --  @
-genPassphrase :: RandomGen g
-              => Int        -- ^ number of words
-              -> Int        -- ^ minimum word length
-              -> Int        -- ^ maximum word length
-              -> GenOptions -- ^ options
-              -> g          -- ^ random generator
-              -> ([String], g)
+genPassphrase
+  :: RandomGen g
+  => Int        -- ^ number of words
+  -> Int        -- ^ minimum word length
+  -> Int        -- ^ maximum word length
+  -> GenOptions -- ^ options
+  -> g          -- ^ random generator
+  -> ([String], g)
 genPassphrase n min max = runRand . mkPassphrase n min max
 
 -- |Generate a passphrase using the generator g, returning the result.
@@ -159,13 +167,14 @@
 --  myNewPassphrase :: IO String
 --  myNewPassphrase = newPassphrase 10 6 12 \`liftM\` getStdGen
 --  @
-newPassphrase :: RandomGen g
-               => Int        -- ^ number of words
-               -> Int        -- ^ minimum word length
-               -> Int        -- ^ maximum word length
-               -> GenOptions -- ^ options
-               -> g          -- ^ random generator
-               -> [String]
+newPassphrase
+  :: RandomGen g
+  => Int        -- ^ number of words
+  -> Int        -- ^ minimum word length
+  -> Int        -- ^ maximum word length
+  -> GenOptions -- ^ options
+  -> g          -- ^ random generator
+  -> [String]
 newPassphrase n min max = evalRand . mkPassphrase n min max
 
 -- |Generate a finite number of words of random length (between @min@ and @max@ chars)
@@ -176,51 +185,52 @@
 --  myPassphrase :: IO String
 --  myPassphrase = evalRand (mkPassphrase 10 6 12) \`liftM\` getStdGen
 --  @
-mkPassphrase :: MonadRandom m
-             => Int        -- ^ number of words
-             -> Int        -- ^ minimum word length
-             -> Int        -- ^ maximum word length
-             -> GenOptions -- ^ options
-             -> m [String]
-mkPassphrase n min max opts = replicateM n $
-  getRandomR (min, max) >>= flip mkPassword opts
+mkPassphrase
+  :: MonadRandom m
+  => Int        -- ^ number of words
+  -> Int        -- ^ minimum word length
+  -> Int        -- ^ maximum word length
+  -> GenOptions -- ^ options
+  -> m [String]
+mkPassphrase n min max opts =
+  replicateM n $ getRandomR (min, max) >>= flip mkPassword opts
 
 -- * Internal
 
 -- |Generate two random characters. Uses 'Elocrypt.Trigraph.trigragh'
 --  to generate a weighted list.
-first2 :: MonadRandom m 
-       => GenOptions
-       -> m String
-first2 opts = fromList (map toWeight frequencies) >>= mapM (capitalizeR caps)
+first2 :: MonadRandom m => m String
+first2 = fromList (map toWeight frequencies)
   where toWeight (s, w) = (s, sum w)
-        GenOptions{genCapitals=caps} = opts
 
 -- |Generate the last n characters using previous two characters
 --  and their 'Elocrypt.Trigraph.trigraph'
-lastN :: MonadRandom m => GenOptions -> Int -> String -> m String
-lastN _    0   ls = return ls
-lastN opts len ls = next opts ls >>= lastN opts (len - 1) . (:ls)
+lastN :: MonadRandom m => Int -> String -> m String
+lastN 0 ls = return ls
+lastN len ls = next ls >>= lastN (len - 1) . (: ls)
 
 -- |Generate a random character based on the previous two characters and
 --  their 'Elocrypt.Trigraph.trigraph'
-next :: MonadRandom m 
-     => GenOptions -- ^ options
-     -> String     -- ^ the prefix
-     -> m Char
-next opts prefix = nextLetter prefix >>= capitalizeR caps
-  where GenOptions{genCapitals=caps} = opts
+next
+  :: MonadRandom m
+  => String     -- ^ the prefix
+  -> m Char
+next = fromList . fromJust . findWeights . reverse . take 2
 
--- |Randomly choose a letter from the trigraph
-nextLetter :: MonadRandom m
-           => String  -- ^ the prefix
-           -> m Char
-nextLetter = fromList . fromJust . findWeights . reverse . take 2
+-- |Randomly capitalize at least 1 character. Additional characters capitalize
+-- at a probability of 1/12
+capitalizeR :: MonadRandom m => Int -> String -> m String
+capitalizeR len s = mapM capitalize s >>= capitalize1 len
+  where capitalize ch = fromList [(ch, 12), (toUpper ch, 1)]
 
--- |Randomly capitalize a character 10% of the time
-capitalizeR :: MonadRandom m
-           => Bool    -- ^ Whether to do the capitalization
-           -> Char    -- ^ The character to capitalize
-           -> m Char
-capitalizeR cap c | cap = fromList [(c, 6), (toUpper c, 1)]
-                  | otherwise = return c
+-- |Randomly capitalize 1 character
+capitalize1
+  :: MonadRandom m
+  => Int -- ^ length
+  -> String -- ^ the string to capitalize
+  -> m String
+capitalize1 len s = capitalize1' <$> getRandomR (0, len - 1)
+  where
+    capitalize1' pos =
+      let (prefix, ch : suffix) = splitAt (pos - 1) s
+      in prefix ++ (toUpper ch : suffix)
diff --git a/test/IntegTest/Elocrypt/PassphraseTest.hs b/test/IntegTest/Elocrypt/PassphraseTest.hs
--- a/test/IntegTest/Elocrypt/PassphraseTest.hs
+++ b/test/IntegTest/Elocrypt/PassphraseTest.hs
@@ -103,7 +103,7 @@
         response       <- readHandle out
         
         return $
-          cover (minLen > 80) 20 "long" $ 
+          cover 20 (minLen > 80) "long" $ 
           all (>=1) . map (length . words) . lines $ response
 
 -- |Prints capitals when specified
@@ -118,4 +118,4 @@
     let phrases = lines response
 
     return $
-      cover (any (any isUpper) phrases) 80 "has caps" True
+      cover 80 (any (any isUpper) phrases) "has caps" True
diff --git a/test/IntegTest/Elocrypt/PasswordTest.hs b/test/IntegTest/Elocrypt/PasswordTest.hs
--- a/test/IntegTest/Elocrypt/PasswordTest.hs
+++ b/test/IntegTest/Elocrypt/PasswordTest.hs
@@ -54,7 +54,7 @@
         response <- readHandle out
 
         return $
-          cover (len' > 80) 30 "long" $
+          cover 30 (len' > 80) "long" $
             all (>=1) . map (length . words) . lines $ response
 
 -- |Prints the specified number of passwords
@@ -95,4 +95,4 @@
       let passes = words response
 
       return $
-        cover (any (any isUpper) passes) 80 "has caps" True
+        cover 80 (any (any isUpper) passes) "has caps" True
diff --git a/test/Test/ElocryptTest.hs b/test/Test/ElocryptTest.hs
--- a/test/Test/ElocryptTest.hs
+++ b/test/Test/ElocryptTest.hs
@@ -22,116 +22,105 @@
 
 -- |Passwords have the specified length
 prop_newPasswordHasLen :: Positive Int -> GenOptions -> StdGen -> Bool
-prop_newPasswordHasLen (Positive len) opts gen
-  = length pass == len
+prop_newPasswordHasLen (Positive len) opts gen = length pass == len
   where pass = newPassword len opts gen
 
 -- |Passwords are all lowercase when caps is false
 prop_newPasswordIsLower :: Positive Int -> StdGen -> Bool
-prop_newPasswordIsLower (Positive len) gen
-  = all isLower pass
-  where pass = newPassword len opts gen
-        opts = genOptions{genCapitals = False}
+prop_newPasswordIsLower (Positive len) gen = all isLower pass
+  where
+    pass = newPassword len opts gen
+    opts = genOptions { genCapitals = False }
 
--- |Passwords with caps generates caps
-prop_newPasswordHasCaps :: Positive Int -> StdGen -> Property
-prop_newPasswordHasCaps (Positive len) gen
-  = cover (any isUpper pass) 50 "has caps" $
-      any isLower pass
-  where pass = newPassword (len + 2) opts gen
-        opts = genOptions{genCapitals = True}
+-- |Passwords with caps have at least one capital
+prop_newPasswordHasCaps :: Positive Int -> StdGen -> Bool
+prop_newPasswordHasCaps (Positive len) gen = any isUpper pass
+  where
+    pass = newPassword (len + 2) opts gen
+    opts = genOptions { genCapitals = True }
 
+-- |Most passwords have more than one capital
+prop_newPasswordHasMultipleCaps :: Positive Int -> StdGen -> Property
+prop_newPasswordHasMultipleCaps (Positive len) gen =
+  cover 50 (length (filter isUpper pass) > 1) "has multiple caps"
+    $ any isLower pass
+  where
+    pass = newPassword (len + 2) opts gen
+    opts = genOptions { genCapitals = True }
+
 -- |Third and each successive character is taken from the trigraph
-prop_3rdCharHasPositiveFrequency 
-  :: Positive Int 
-  -> GenOptions 
-  -> StdGen 
-  -> Property
-prop_3rdCharHasPositiveFrequency (Positive len) opts gen
-  = conjoin $ loop pass
-  where pass = newPassword (len+2) opts gen
-        loop (f:s:t:xs) = thirdCharIsInTrigraph [f, s, t] : loop (s:t:xs)
-        loop _          = []
+prop_3rdCharHasPositiveFrequency
+  :: Positive Int -> GenOptions -> StdGen -> Property
+prop_3rdCharHasPositiveFrequency (Positive len) opts gen = conjoin $ loop pass
+  where
+    pass = newPassword (len + 2) opts gen
+    loop (f : s : t : xs) = thirdCharIsInTrigraph [f, s, t] : loop (s : t : xs)
+    loop _ = []
 
 thirdCharIsInTrigraph :: String -> Property
-thirdCharIsInTrigraph pass
-  = counterexample failMsg $ property (t `elem` candidates)
-  where (f:s:t:_) = map toLower pass
-        candidates = map fst . filter ((0/=) . snd) $ frequencies
-        frequencies = zip ['a'..'z'] .
-                      defaultFrequencies .
-                      fromJust .
-                      findFrequency $ [f, s]
+thirdCharIsInTrigraph pass = counterexample failMsg
+  $ property (t `elem` candidates)
+  where
+    (f : s : t : _) = map toLower pass
+    candidates = map fst . filter ((0 /=) . snd) $ frequencies
+    frequencies =
+      zip ['a' .. 'z'] . defaultFrequencies . fromJust . findFrequency $ [f, s]
 
-        failMsg = t : " not in [" ++ candidates ++ "]"
+    failMsg = t : " not in [" ++ candidates ++ "]"
 
 -- First 2 characters have total non-zero frequencies
-prop_first2HavePositiveFrequencies 
-  :: Positive Int
-  -> GenOptions
-  -> StdGen
-  -> Property
-prop_first2HavePositiveFrequencies (Positive len) opts gen
-  = counterexample failMsg $ property (sum frequencies > 0)
-  where pass = newPassword (len+1) opts gen
-        (f:s:_) = map toLower pass
-        frequencies = zipWith (curry snd) ['a'..'z'] .
-                      fromJust .
-                      findFrequency $ [f, s]
-        failMsg = "no candidates for '" ++ [f, s] ++ "'"
+prop_first2HavePositiveFrequencies
+  :: Positive Int -> GenOptions -> StdGen -> Property
+prop_first2HavePositiveFrequencies (Positive len) opts gen =
+  counterexample failMsg $ property (sum frequencies > 0)
+  where
+    pass = newPassword (len + 1) opts gen
+    (f : s : _) = map toLower pass
+    frequencies =
+      zipWith (curry snd) ['a' .. 'z'] . fromJust . findFrequency $ [f, s]
+    failMsg = "no candidates for '" ++ [f, s] ++ "'"
 
 -- (len . fst) (genPasswords _ x _ _) = x
 prop_newPasswordsHasLen
-  :: Positive Int
-  -> Positive Int
-  -> GenOptions
-  -> StdGen
-  -> Property
-prop_newPasswordsHasLen (Positive len) (Positive num) opts gen
-  = counterexample failMsg $ property (length passes == num)
-  where passes = newPasswords len num opts gen
-        failMsg     = show (length passes) ++ " /= " ++ show num
+  :: Positive Int -> Positive Int -> GenOptions -> StdGen -> Property
+prop_newPasswordsHasLen (Positive len) (Positive num) opts gen =
+  counterexample failMsg $ property (length passes == num)
+  where
+    passes = newPasswords len num opts gen
+    failMsg = show (length passes) ++ " /= " ++ show num
 
 -- (all ((x==) . length) . fst) (genPasswords x _ _ _) = x
 prop_newPasswordsAllHaveLen
-  :: Positive Int
-  -> Positive Int
-  -> GenOptions
-  -> StdGen
-  -> Bool
-prop_newPasswordsAllHaveLen (Positive len) (Positive num) opts gen
-  = all ((len==) . length) passes
+  :: Positive Int -> Positive Int -> GenOptions -> StdGen -> Bool
+prop_newPasswordsAllHaveLen (Positive len) (Positive num) opts gen = all
+  ((len ==) . length)
+  passes
   where passes = newPasswords len num opts gen
 
 -- |Given the same generator, newPassword and genPassword generates the 
 --  same password.
 prop_newPasswordMatchesGenPassword
-  :: Positive Int
-  -> GenOptions
-  -> StdGen
-  -> Property
-prop_newPasswordMatchesGenPassword (Positive len) opts gen
-  = counterexample failMsg $ property (pass == pass')
-  where (pass, _) = genPassword len opts gen
-        pass'     = newPassword len opts gen
-        failMsg   = show pass ++ " /= " ++ show pass'
+  :: Positive Int -> GenOptions -> StdGen -> Property
+prop_newPasswordMatchesGenPassword (Positive len) opts gen =
+  counterexample failMsg $ property (pass == pass')
+  where
+    (pass, _) = genPassword len opts gen
+    pass' = newPassword len opts gen
+    failMsg = show pass ++ " /= " ++ show pass'
 
 -- |Given the same generator, newPasswords and genPasswords genereates
 --  the same passwords.
 prop_newPasswordsMatchesGenPasswords
-  :: Positive Int
-  -> Positive Int
-  -> GenOptions
-  -> StdGen
-  -> Property
-prop_newPasswordsMatchesGenPasswords (Positive len) (Positive num) opts gen
-  = counterexample failMsg $ property (passes == passes')
-  where (passes, _) = genPasswords len num opts gen
-        passes'     = newPasswords len num opts gen
-        failMsg     = show passes ++ " /= " ++ show passes'
+  :: Positive Int -> Positive Int -> GenOptions -> StdGen -> Property
+prop_newPasswordsMatchesGenPasswords (Positive len) (Positive num) opts gen =
+  counterexample failMsg $ property (passes == passes')
+  where
+    (passes, _) = genPasswords len num opts gen
+    passes' = newPasswords len num opts gen
+    failMsg = show passes ++ " /= " ++ show passes'
 
 -- |newPassphrase generates n words
-prop_newPassphraseHasLen 
+prop_newPassphraseHasLen
   :: Positive Int
   -> Positive Int
   -> Positive Int
@@ -140,8 +129,9 @@
   -> Property
 prop_newPassphraseHasLen (Positive len) (Positive min) (Positive max) opts gen
   = counterexample failMsg $ property (length words == len)
-  where words   = newPassphrase len min max opts gen
-        failMsg = show len ++ " /= length " ++ show words
+  where
+    words = newPassphrase len min max opts gen
+    failMsg = show len ++ " /= length " ++ show words
 
 -- |newPassphrase generates words in the allowed range
 prop_newPassphraseWordsHaveLen
@@ -151,11 +141,11 @@
   -> GenOptions
   -> StdGen
   -> Bool
-prop_newPassphraseWordsHaveLen
-  (Positive len) (Positive min) (Positive max) opts gen
+prop_newPassphraseWordsHaveLen (Positive len) (Positive min) (Positive max) opts gen
   = all (\w -> length w >= min && length w <= max') words
-  where words = newPassphrase len min max' opts gen
-        max'  = min + max
+  where
+    words = newPassphrase len min max' opts gen
+    max' = min + max
 
 -- |Given the same generator, genPassphrase and newPassphrase generates
 -- the same passphrase
@@ -166,10 +156,10 @@
   -> GenOptions
   -> StdGen
   -> Property
-prop_genPassphraseMatchesNewPassphrase 
-  (Positive len) (Positive min) (Positive max) opts gen 
+prop_genPassphraseMatchesNewPassphrase (Positive len) (Positive min) (Positive max) opts gen
   = counterexample failMsg $ property (words == words')
-  where (words, _) = genPassphrase len min max' opts gen
-        words'     = newPassphrase len min max' opts gen
-        max'       = min + max
-        failMsg    = show words ++ " /= " ++ show words'
+  where
+    (words, _) = genPassphrase len min max' opts gen
+    words' = newPassphrase len min max' opts gen
+    max' = min + max
+    failMsg = show words ++ " /= " ++ show words'
