Although the article talks about the limitation of (purely) type driven/guided development, I'm still wondering how programmers in non-functional land like me get some benefit from these type driven style.
Arguably, from a type-radical perspective, this is often because types were not specific enough. In the first case, the problem is quite obvious from the fact that genAp doesn’t ask for Gen t (or something else that would guide it into generating forms of t). (Of course, Haskell’s type-system and libraries are not at the level of expressiveness to make perfect type signatures always easy)
Now, in the second case, the problem IMO is mixed logic/duplication in ‘maybe spawn (killThread $> spawn) oldId‘. How about ‘ forM_ oldId killThread’, followed by spawn?
I feel like there could be some valuable information here, but not knowing Haskell is a huge barrier for me. Anybody know what an analogous example would be in something like TypeScript or Java?
The concept is somewhat lost in translation because ML-type languages and Haskell especially push you towards using type signatures as a way to build your functions, "following the types", as the article puts it. This is more productive in Haskell because the type system is much more expressive than TS or Java.
The main difference in the type systems is that Haskell requires you to annotate effects, where OO languages usually don't. For example, a Java method with signature:
<T extends Number> T f(T x, T y)
could possibly open a network socket, print to stdout, delete a file, launch an ICBM, etc. OTOH a Haskell function with signature
f :: (Num a) => a -> a -> a
is a pure function of its inputs.
The idea of the article is that even a stronger type system isn't by itself a guarantee of correctness, you could very well have a program that types correctly but is still wrong, the type system only protects you from some errors.
Paradoxically, because OO type systems are weaker, it's harder to fall in this specific trap: we know that we can only trust the type system so much.
The closest analogy I can think of in an OO language is breaking a contract of a class by calling a method of a superclass.