upvote
The gist is that "kinds" allow you to write generic types which themselves take generic types as type parameters.

For a concrete example, suppose that you want to define a data type for JSON objects. You would likely need to choose a type to represent JSON arrays (such as `ArrayList`, in Java), as well as a type to represent JSON objects (such as `HashMap`). However, what if the client wanted to use `TreeMap` instead of `HashMap`?

With "kinds," you would be able to define the JSON data type as something abstract like `JSON<ArrayType, MapType>`, and allow the client to instantiate it as `JSON<ArrayList, HashMap>` or `JSON<ArrayList, TreeMap>`. Unfortunately, in a language such as Java, this is not possible, because `ArrayList`, `HashMap`, and `TreeMap` are themselves generic types, while only non-generic types (such as `Integer`, `String`, or `HashMap<String, Integer>`) can be type parameters. However, in a language with higher-kinded types, such as Scala, this becomes possible.

In these higher-kinded languages, a type such as `Integer` or `HashMap<String, Integer>` would have a "kind" of `*`, while a generic type such as `ArrayList` would have a kind of `* -> *` (meaning: a generic type of one, non-generic type parameter), and `HashMap` and `TreeMap` would both have a "kind" of `* -> * -> *` (meaning: a generic type of two, non-generic type parameters).

C++'s templates permit a similar abstraction to higher-kinded types, and the library nlohmann::json (https://json.nlohmann.me/api/basic_json/) in fact does something very similar to the JSON example that I describe. Namely, it uses `std::vector` as the default for `ArrayType` and `std::map` as the default for `MapType`, but also allows the client to parameterize the underlying container of choice. However, C++ templates need to be fully expanded in order to be typechecked, leading to compile-time error messages that can be long and difficult to read. A "kind" system basically solves this issue by imposing a proper type system onto templates, allowing for more understandable error messages.

reply
Great Explanation!

See also: Concepts for higher-kinded types in C++20 - https://mmore500.com/cse-491/blog/2020/02/24/concepts-monads...

reply
deleted
reply
> As any problem can be expressed in C, how would what the author did look like in C? KISS

This is C.

  void * bsearch (const void *key, const void *array, size_t count, size_t size, comparison_fn_t compare)
How do you express "the thing you get back has the same type as the thing you're looking for"?
reply
You don't. Or less snarky, I imagine you'd have to use macros to generate wrapper functions, in order to generate a new function of a user provided type.
reply