Q: Curious about why get in StateT monad transformer returns a instead of (a, s) I was reading the StateT monad transformer's source, as it reads like this:
get :: (Monad m) => StateT s m s
get = state $ \ s -> (s, s)

I expanded the above code by switching out state and got this, but still fail to see why it's not returning a tuple.
a <- StateT (return . (\ s -> (s, s)))

From the code above it seemed get returns a tuple (s, s), which looked fine, but I'm wondering why when using it, get returned an Int, instead of (Int, Int)? 
I traced a lot of source code trying to find when or what changed it but to no avail.
w :: StateT Int IO String
w = do
  a <- get
  liftIO $ print a -- 2, but why? shouldn't this be (2, 2) instead?
  return $ show a

result = runStateT w 2 -- ("2",2)



A: A value of type StateT s m a, modulo newtype wrappers, is a function with type s -> m (a, s).
The function (return . (\ s -> (s, s))) has type s -> m (s, s), hence once it is wrapped by the StateT constructor becomes a value of type StateT s m s.
Note that a value of type StateT s m (s, s) would instead involve a function of type s -> m (s, (s, s)) which is not what we are using here.
Your confusion seem to arise from the "other" s in m (s, s), which does not contribute to x when we run x <- get. To understand why, it's useful to think to think to what a stateful computation performs:


*

*First, we read the old state of type s. This is the s -> .. part in the type s -> m (a, s).

*Then, we run some action in the monad m. This is the .. -> m .. part in the type s -> m (a, s).


*

*The monadic action returns a new state, to replace the old one. This is the .. -> .. (.., s) part in the type s -> m (a, s).

*Finally, monadic action also returns a value, of a possibly different type a. This the .. -> .. (a, ..) part in the type s -> m (a, s).



Running x <- action handles all these types automatically for us, and lets x to have the result type a, only.
Concretely, consider this imperative pseudo-code:
global n: int

def foo():
   if n > 5:
      print ">5"
      n = 8
      return "hello"
   else:
      print "not >5"
      n = 10
      return "greetings"

In an imperative language, we would type this as foo(): string, since it returns a string, disregarding its side effects to the global n: int and the printed messages.
In Haskell, we would instead model that using a more precise type like
Int -> IO (String, Int)
^-- the old n
       ^-- the printed stuff
           ^-- the returned string
                   ^-- the new n

Again, running x <- foo() we want x: string, not x: (string, int), following what would happen in an imperative language.
If instead we had a function
global n: int

def bar():
   old_n = n
   n = n + 5
   return old_n

we would use the type
Int -> IO (Int, Int)

since the returned value is an Int now. Similarly,
global n: int

def get():
   return n

could use the same type
Int -> IO (Int, Int)

Now, one might argue that the second Int is not strictly necessary here, since get() is not really producing a new state -- it's not changing the value of n. Still, it's convenient to use a type of the same form, s -> m (a, s), as any function which could change the state. This is so that it can be used together with any other function having a similar type.
