Am I thinking functionally in these simple Haskell functions?
Overall it's pretty nice. I like that you've learned how to use $; it really improves readability in my opinion. One thing that immediately caught my attention though was the chain of prints. Haskell can do better! You can for example put those in a list, and mapM_ print over it.

let fns = 
    [ skips "ABCD"
    , skips "hello!"
    , skips [1]
    , skips [True, False]
    , skips ([] :: [Int])
    , localMaxima [2,9,5,6,1]
    , localMaxima [2,3,4,1,5]
    , localMaxima [1,2,3,4,5]
    ]

mapM_ print fns


This makes it easier to refactor  later, if you want to do something else than print, write them to different files, all kinds of stuff. The lisp-ish approach of code-as-data is quite useful when enumerating cases like you did here.



isMiddleMax (x:y:z:[]) = x &lt; y &amp;&amp; y &gt; z


Spooky! Use -Wall to get a proper warning for that one: incomplete patterns in function .... You might want to consider adding a meaningful error message:

isMiddleMax _ = error "Only works on 3-element lists!"




triples (x:xs)
  | length (x:xs) &lt; 3 = []


Dunno if you know, but there exists a thing called "alternate name capture"; it's written like so:

triples (x:xs @ allXs)
  | length allXs &lt; 3 = []


If you consider this an overkill, why not simply change the clause to length xs &lt; 2? I don't like the same pattern repeated for some reason.



countInstances xs = map (countInstance) $ groupSort xs

maxInstances xs = maximum $ map (snd) $ countInstances xs


The parens around countInstance and snd are unnecessary (it's not terrible to leave them, just pointing that out). HLint is a useful tool that can provide such hints for you!



Oh, and also, in the second case; multiple $ are a bit less readable; consider this instead:

maxInstances xs = maximum . map (snd) . countInstances $ xs


This expresses it in a truly functional way, and makes it susceptible to eta-reduction!:

maxInstances = maximum . map (snd) . countInstances


This is called point-free (not to be confused with pointless :)) notation, and makes it extremely clear that the function is indeed a composition of other functions ((.) is Haskell's composition operator).



I'll add more if I notice any more areas for improvement.