-- This is double using function overloading.
double :: Num a => a -> a
double x = x+x

-- This is quad, using function composition and overloading. Like a boss.
quad :: Num a => a -> a
quad = double . double

-- This is sparta.
factorial :: Integer -> Integer
factorial n = product [1..n]

-- Average with an operator instead of a function
average :: [Int] -> Int
average numbers = (sum numbers) `div` (length numbers)

{-
	here, the type signature has to be [Int] -> Int and not
	Num a => [a] -> Int because even though sum has signature 
	sum :: Num a => [a] -> a, suggesting that numbers could be a Num a => [a],
	length has signature length :: [a] -> Int, producing Ints. Now, div, which is
	the last function to be executed, has type div :: Integral a => a -> a -> a
	meaning that as long as a is an Integral, all its arguments must have the
	same type a. Since Int is an Integral and a Num, Int has to be used. 
-}

-- Another way to get last, function composition like a pro
newLast :: [a] -> a
newLast = head.reverse

-- Yet another way to get last, recursion, the old fashioned way
anotherLast :: [a] -> a
anotherLast [x]    = x
anotherLast (x:xs) = anotherLast xs

-- Another way to do init, the weirdestly named function ever
newInit :: [a] -> [a]
newInit xs = take (length xs -1) xs

-- And yet another way because we cannot get enough of this
anotherInit :: [a] -> [a]
anotherInit [x,y] = [x]
anotherInit (x:xs) = x:anotherInit xs

