Finding word acronyms for telephone numbers
This is pretty nice code.

I have two main concerns. The first one is about handling errors.
You are mixing tree approaches: Maybe, throwing explicit error, throwing implicit error (as in readNumber).
It's better to stick to Maybe or Either — they are explicit and you can handle them in pure code.

The second one is about dividing your program in meaningful functions each having single responsibility. Such functions are simpler and you can more easily compose them.

For example, getMatches checks if dictionary is not empty, adds \b to pattern and matches pattern.
It is better to split error handling from data processing (in this case by lifting dictionary check to main).

Another one is readNumber: it parses string into list of digits and implicitly checks for nondigits (throwing useless 'no parse' error).
You can skip this as you check for invalid symbols in toRegex.



Some other remarks:


the type of toRegex is so general that it almost useless. I think you actually meant Integer -&gt; Maybe String;
in parseList you first scanning list for Nothing and then catMaybes scanning it again to remove Nothings. It is possible to do this in single pass by using sequence.


Here is my take:

{-# LANGUAGE OverloadedStrings #-}

import Text.Regex.TDFA
import qualified Data.ByteString.Char8 as B
import Data.Monoid ((&lt;&gt;))
import Control.Monad (when)
import System.Exit (die)
-- `die` was introduced in the latest base, you can replace it with
-- die err = putStrLn err &gt;&gt; exitFailure

main = do
  dictionary &lt;- B.readFile "words.txt"
  when (dictionary == "") $ die "Your dictionary is empty."

  putStrLn "What is your phone number?"
  phoneNumber &lt;- getLine
  case toPattern phoneNumber of
    Nothing -&gt;
      die "Some input was incorrect. Make sure no letters or numbers with 0 or 1 are being used."
    Just pattern -&gt; case getAllTextMatches $ dictionary =~ pattern of
      []  -&gt; B.putStrLn $ "Sorry. No matches were found."
      res -&gt; B.putStrLn $ "Matching words: \n" &lt;&gt; B.unlines res


toPattern :: String -&gt; Maybe B.ByteString
toPattern str = do
  parts &lt;- sequence $ map toRegex str
  return $ "\\b" &lt;&gt; B.concat parts &lt;&gt; "\\b"


toRegex :: Char -&gt; Maybe B.ByteString
toRegex = flip lookup
  [('2', "(a|b|c)")    ,('3', "(d|e|f)")
  ,('4', "(g|h|i)")    ,('5', "(j|k|l)")
  ,('6', "(m|n|o)")    ,('7', "(p|q|r|s)")
  ,('8', "(t|u|v)")    ,('9', "(w|x|y|z)")
  ]