Printing right triangles recursively in Haskell
The recursion you used is very cumbersome, and should be avoided in favour of more expressive solutions in Haskell.  You figured out how to write replicate n c — why didn't you just run with that?  Add some list comprehensions, and you're done!

Instead of using recursion in printTriangle to print one line at a time, you can just write putStr $ unlines.

Naming each function starting with "make…" feels a bit redundant to me.

Splitting the menu between getTriangleType and makeTriangle is awkward.  You're using an integer to represent the type of triangle, and the two functions have to agree on which number represents which orientation.  The most natural way to represent a type of triangle is to use the corresponding triangle-generating function itself!  And I'd define a type synonym TriangleMaker for those functions.

type TriangleMaker = Char -&gt; Int -&gt; [String]

topLeftTriangle :: TriangleMaker
topLeftTriangle c n = [replicate i c | i &lt;- [n, n-1 .. 1]]

bottomLeftTriangle :: TriangleMaker
bottomLeftTriangle c n = [replicate i c | i &lt;- [1 .. n]]

topRightTriangle :: TriangleMaker
topRightTriangle c n =
  [(replicate (n - i) ' ') ++ (replicate i c) | i &lt;- [n, n-1 .. 1]]

bottomRightTriangle :: TriangleMaker
bottomRightTriangle c n =
  [(replicate (n - i) ' ') ++ (replicate i c) | i &lt;- [1 .. n]]

getTriangleType :: IO TriangleMaker
getTriangleType = do
  let menu = [topLeftTriangle, bottomLeftTriangle, topRightTriangle, bottomRightTriangle]
  putStr $ unlines [ 
    "What type of triangle do you want to print? (1, 2, 3, or 4)",
    "1) Top Left",
    "2) Bottom Left",
    "3) Top Right",
    "4) Bottom Right"]
  line &lt;- getLine
  return (menu !! ((read line :: Int) - 1))

main :: IO ()
main = do
  triangle &lt;- getTriangleType
  size &lt;- getLine
  putStr $ unlines $ triangle '*' (read size :: Int)