3 ms·
> I'd say most of the time, you just failed to capture the commonalities. More specifically, you seek generality through exhaustiveness, when you should use gen
by tel 13y ago
> I'd say most of the time, you just failed to capture the commonalities. More specifically, you seek generality through exhaustiveness, when you should use genericness instead.
THIS is one of the most important things I've ever learned from programming Haskell[0]. The way to make things generic is to whittle away all of the sharp edges and implement them as compositions atop base patterns. Those base patterns arise out of polymorphism, not exhaustiveness.
You don't make lists generic by realizing that you need a list type to have all the properties of a string, a tree, a vector... You make it generic by realizing that much of its structure arises by forgetting what's inside.
[0] Which is not to say you can't learn it elsewhere, or that you cannot do it elsewhere. Instead, Haskell has the facility, the philosophy, and the community to do it really effectively all the time and so if you read Haskell code you'll be floored by some of the great examples possible there.
- loup-vaillant 13y agoFun fact: I have known this intuitively since forever, but only recently realized that when I say "generic", most programmers I know tend to hear "exhaustive", and recoil in horror; while I really meant "generic". Now, I also know why I like parametric polymorphism, and dislike subclass polymorphism: the first is generic, while the second is exhaustive.
- mushly 13y agoWhat's the difference between "generic" and "exhaustive," and where can I read more about all this stuff?
- loup-vaillant 13y agoImagine you want to process a list of foobarbaz, where elements can be foos, bars, or bazes. Exhaustion is when you write foo specific code, bar specific code, and baz specific code. Then your list-processing facility is general because it handles all the cases. A typical way to do that in practice is to use subtype polymorphism, with the class inheritance mechanism: have a foobarbaz interface, a foo class that implements it, a bar class that implements it, and a baz class that implements it. Each with their own code. Genericness is when you ignore the foobarbaz specifics altogether: your code doesn't even mention the types. A typical way to do that in practice is to use parametric polymorphism (generics in Java, templates in C++). See C++'s Algorithm library for an example, or the standard Prelude from Haskell, or the OCaml standard library.
- tel 13y ago> Now, I also know why I like parametric polymorphism, and dislike subclass polymorphism: the first is generic, while the second is exhaustive. I'm going to steal that. I love it.