Haskell Convert 1-800 Numbers
Type signatures

Good job on providing all type signatures. Unfortunately, you forgot one: enter. Always include type signatures on top-level functions.

Remove unused imports

You use neither Data.List, nor System.IO.

Prefer character comparison instead of ord x &gt; n

In getDigit, you compare characters by their ord values. That's not easy on the eye. It's a lot easier to read if you just compare the letter with characters:

getDigit :: Char -&gt; Int
getDigit letter
    | letter &gt;= 'a' &amp;&amp; letter &lt;= 'c' = 2
    | letter &lt;= 'f' = 3
    | letter &lt;= 'i' = 4
    | letter &lt;= 'l' = 5
    | letter &lt;= 'o' = 6
    | letter &lt;= 's' = 7
    | letter &lt;= 'v' = 8
    | letter &lt;= 'z' = 9
    | otherwise = 0


There are other ways to write getDigit, but I they differ on personal preference only.

Use the standard library

stripDashes is filter (/= '-') in disguise:

stripDashes xs = [ x | x &lt;- xs, not (elem x  "-")]
               = [ x | x &lt;- xs, x /= '-']
               = filter (/= '-') xs


Therefore use filter instead of a list comprehension:

stripDashes :: String -&gt; String
stripDashes = filter (/= '-')


By the way not (elem x y) is notElem x y.

Prefer local bindings instead of long lines

This is personal preference, but I think that

convertLetters :: String -&gt; String
convertLetters xs = map toDigit xs
  where
    toDigit x 
     | isNumber x = x 
     | otherwise  = intToDigit $ getDigit $ toLower x


is easier to read.

Use hlint to get rid of redundant brackets

You have a lot of redundant brackets, which can make the code hard to read. hlint can report them to you. It also reports the not (elem x y) == notElem x y hint, by the way.

Prefer pure functions if possible

You have enter for a complete transformation. It would be great if there was a non-IO variant too, e.g.

convert :: String -&gt; String
convert = insertDashes . convertLetters . stripDashes


That way you can export enter, conver and stripDashes.

Use splitAt instead of take/drop combinations

Finally, we have a look at insertDashes. First of all, let's write bindings:

insertDashes :: String -&gt; String
insertDashes xs = group1 ++ ['-'] ++ group2 ++ ['-'] ++ group3 ++ ['-'] ++ group4 
   where
      group1 = take 1 xs
      group2 = take 3 (drop 1 xs)
      group3 = take 3 (drop 4 xs)
      group4 = take 4 (drop 7 xs)


That looks like a perfect job for splitAt:

-- do not include this function in your code, it's part of the Prelude
splitAt n xs = (take n xs, drop n xs)


However, if we were to rewrite insertDashes with splitAt, it wouldn't get any better immediately:

import Data.List (intercalate)

insertDashes :: String -&gt; String
insertDashes xs = group1 ++ ['-'] ++ group2 ++ ['-'] ++ group3 ++ ['-'] ++ group4 
   where
      (group1,ys1) = splitAt 1 xs
      (group2,ys2) = splitAt 3 ys1
      (group3,ys3) = splitAt 3 ys2
      (group4,_  ) = splitAt 4 ys3


Ugh. Not really any better. So instead let's write another function:

splitAtNs :: [Int] -&gt; [a] -&gt; [[a]]
splitAtNs []     xs = [xs]
splitAtNs (n:ns) xs = as : splitAtNs ns bs
  where (as, bs) = splitAt n xs


Now  insertDashes is

insertDashes :: String -&gt; String
insertDashes xs = group1 ++ ['-'] ++ group2 ++ ['-'] ++ group3 ++ ['-'] ++ group4 
   where
      (group1:group2:group3:group4:_) = splitAtNs [1,3,3,4] xs


Which almost looks fine. There is one more improvement, though. The function intercalate from Data.List brings it down to a single line:

insertDashes :: String -&gt; String
insertDashes = intercalate "-" . take 4 . splitAtNs [1,3,3,4]