Safe Reverse Polish Notation
This:


maybeStringToMaybeDouble x = do
      y &lt;- x
      maybeRead y



Could be:

maybeStringToMaybeDouble x = x &gt;&gt;= maybeRead


Similarly,


safeHead m = do
    x &lt;- m
    listToMaybe x



Could be

safeHead m = m &gt;&gt;= listToMaybe


Or we could remove these functions entirely and just write

rpn xs = foldM foldingOp [] (words xs) &gt;&gt;= listToMaybe &gt;&gt;= maybeRead


It seems strange that we're importing Network.CGI.Protocol for maybeRead. I would suggest using readMaybe from Text.Read instead.

There's a chance to use isJust here:


matches' :: Regex -&gt; String -&gt; Bool
matches' r x 
   | matchRegex r x == Nothing = False
   | otherwise                 = True



matches' :: Regex -&gt; String -&gt; Bool
matches' r x = isJust $ matchRegex r x


We can do away with six functions by rewriting foldingOp like this:

foldingOp :: [String] -&gt; String -&gt; Maybe [String]
foldingOp acc s 
   | isNumber s = Just (s : acc)
   | s == "+"   = performOp Add acc
   | s == "-"   = performOp Subtract acc
   | s == "*"   = performOp Multiply acc
   | otherwise  = Nothing


And we can simplify further by removing the Operator type:

foldingOp :: [String] -&gt; String -&gt; Maybe [String]
foldingOp acc s 
   | isNumber s = Just (s : acc)
   | s == "+"   = performOp (+) acc
   | s == "-"   = performOp (-) acc
   | s == "*"   = performOp (*) acc
   | otherwise  = Nothing

performOp :: (Double -&gt; Double -&gt; Double) -&gt; [String] -&gt; Maybe [String]
performOp o (x:y:zs) = Just $ doOp o x y : zs
performOp _ _        = Nothing

doOp :: (Double -&gt; Double -&gt; Double) -&gt; String -&gt; String -&gt; String
doOp op a b = show $ (read b :: Double) `op` (read a :: Double)