It's easier to make the parallel between type-level and value-level reasoning.
1 is a value, and int is a concrete type.
function increment(x) { return x + 1 } is a value-level function. You feed it a value x and you get a value back. List is a type-level function: you give it a concrete type T, you get another type back.
function applyTwice(f, x) { return f(f(x)) } is a higher-order function that takes a functions as an input. A higher-kinded type is a higher-order type function.
As a concrete example, consider this pseudo-Java method:
List map(Function fn, List as) { ... }
You take a list, and you return a list. Thing is, Java has several list implementations: LinkedList, ArrayList, CopyOnWriteArrayList, and a few others. What I'd like to express is that whatever concrete list type goes in is
also the concrete type that comes out. If java allowed it, you could express it like this:
L map extends List,A,B>(Function fn, L as) { ... }
This map is generic on L, A, and B, but also L is itself generic, so map is "twice-generic", if you will.