Factorials and Powers calculator
The rise for power

Let's start with powerInternal. First of all, there's a better algorithm for \$b^e\$, which takes \$\mathcal O(\log e)\$ instead of \$\mathcal O(e)\$:

$$b^e = \begin{cases}\left(b^2\right)^\frac{e}{2},&amp;e~\text{even}\\
b\left(b^2\right)^\frac{e-1}{2},&amp;e~\text{odd}\\
\end{cases}
$$

Implementing this is left as an exercise. But it seems like you want to use powerInternal only in power, since it doesn't work with negative exponents. Therefore, you should reduce its scope:

power :: Double -&gt; Integer -&gt; Double
power b e = if e &gt;= 0
    then powerInternal b e
    else 1 / powerInternal b (-e)
  where
    powerInternal :: Double -&gt; Integer -&gt; Double
    powerInternal b 0 = 1
    powerInternal b e = b * powerInternal b (e - 1)


However, we're reinventing the wheel. There's already a function of type 

(Fractional a, Integral b) =&gt; a -&gt; b -&gt; a


that supports negative exponents. It's called (^^). So we can change your power function:

power :: Double -&gt; Integer -&gt; Double
power b e = b ^^ e
-- or, shorter, but less readable
-- power = (^^)


This is probably the shortest variant you can get. Onwards

Don't trust the user

What do you want to do (0=quit, 1=factorial, 2=power) abc
Run.hs: Prelude.read: no parse


Users will provide wrong input. Either because they intended to do so, or because their finger slipped and they accidentally put 12 instead of 1. If you don't want your program to crash, you probably want to ask again instead. Therefore, we should probably use a function:

askUser :: IO Int
askUser = do
  putStr "What do you want to do? (0: quit; 1: factorial; 2: power) "
  input &lt;- getLine


We have now several ways to handle this. We could use case

  case input of
    "0" -&gt; return 0
    "1" -&gt; return 1
    "2" -&gt; return 2
    _   -&gt; putStrLn "Wrong input, please try again" &gt;&gt; askUser


but that's error prone. Instead, we use readMaybe from Text.Read:

  let input' = readMaybe input

  if 0 &lt;= input' &amp;&amp; input' &lt;= 2
     then return input'
     else putStrLn "Wrong input, please try again" &gt;&gt; askUser


We can shorten it if we use fmap readMaybe getLine:

askUser :: IO Int
askUser = do
  putStr "What do you want to do? (0: quit; 1: factorial; 2: power) "
  input &lt;- fmap readMaybe getLine

  case input of
     Just x | 0 &lt;= x &amp;&amp; x &lt;= 2 -&gt; return x
     _                         -&gt; putStrLn "Wrong input, please try again" &gt;&gt; askUser


Now we know that askUser will always return a number in the range 0-2. 

Foul magic

However, what's 0? What is 1? All three numbers are magic numbers, which is usually a code smell. You, as a developer, have to remember what a certain number stands for. Save them somewhere, like

userQuit, userFactorial, userPower :: Int
userQuit      = 0
userFactorial = 1
userPower     = 2


Now you can write

if answer == userQuit


instead of

if answer == 0


But aren't the choices of the user rather limited in comparison to Int? How about

data UserChoice = Quit | Factorial | Power deriving (Enum, Bounded, Show)


instead? Now we can use

askUserChoice :: IO UserChoice
askUserChoice = fmap toEnum askUser


to convert 0-2 to our own enumeration.

Now, with askUserChoice, we get the following main:

main :: IO ()
main = do
  hSetBuffering stdout NoBuffering

  input &lt;- askUserChoice

  case input of
    Quit      -&gt; exitSuccess
    Factorial -&gt; userFactorial &gt;&gt; main
    Power     -&gt; userPower     &gt;&gt; main


I will come to the yet unknown functions in a second. What did we gain so far? Well, input is going to be a valid answer when we try to inspect it, and we can pattern match on it. Even better, the compiler can tell us that we forgot a pattern if we decide to add Addition or something similar later.

Splitting hairs and concerns

Now to the user* functions. They are pretty much the same as yours, with a small twist:

userFactorial :: IO ()
userFactorial = do
    num &lt;- getInteger "a number"
    putStrLn ("The factorial of " ++ show num ++ " is: " ++ show (factorial num))    

userPower :: IO ()
userPower = do
    base &lt;- getInteger "the base number"
    expe &lt;- getInteger "the exponent"    
    putStrLn (show base ++ "^" ++ show expe ++ " = " ++ show (power base expe))


The twist is, that getInteger will ask the user till they actually provide an integer:

getInteger :: String -&gt; IO Integer
getInteger what = do
    putStrLn ("Enter " ++ what ++ ": ")
    hFlush stdout

    input &lt;- fmap readMaybe getLine

    case input of
      Nothing -&gt; putStrLn "Not a number, please try again." &gt;&gt; getInteger what
      Just x  -&gt; return x


Summary

So, what has been improved? 


The power function uses (^^), a standard library function
We check user input for validity 
We don't read values multiple times
We show our intentions for the user's action with a data type
We provide a succinct main and let other functions handle the actual work
We share common problems (getting an integer from the user) and don't repeat ourselfs.


From a beginners perspective, your code is fine, by the way. Some will tell you to use ($) instead of parentheses in your putStrLn lines, but that's a personal preference. The only two real problems where the suboptimal power, and that you don't actually check user input.

Bonus: Short alternative main

Well, the data type and so on is an overkill. We can check the initial decision a lot easier if we simply don't convert the result of getLine into a number (or another type):

main = do
  putStr "What do you want to do (0=quit, 1=factorial, 2=power) "
  input &lt;- getLine

  case input of
    "0" -&gt; exitSuccess
    "1" -&gt; userFactorial &gt;&gt; main
    "2" -&gt; userPower     &gt;&gt; main
    _   -&gt; putStrLn "Wrong input, try again!" &gt;&gt; main


The key to getting main succinct here is still to split the code into another function. You can provide the code inline, but that's hardly readable anymore.