But I don't want to spend any more time near purely functional programmers in my professional life, so I will spend some time to unfairly nitpick the article.
> a lot of the new features ... are either inspired by, or at least more robustly implemented in, Haskell.
This is like some programmers, who don't know much about the history of programming languages, saying Java is stealing features from Kotlin (a language I enjoy). In both cases the inspiration usually comes from ML (a language family which includes OCaml - a language I deeply admire).
Type classes (first implemented in Haskell) are neat though. I heard that Java is considering adopting them.
> Let’s imagine we represented these as plain old strings ... `Theatre String String -- venue name and event name respectively` `checkForSeats :: String -> String -> IO [Seat]`
If your language has named arguments, and sum type cases are records where you have to name your fields, using plain strings is just fine, and probably more ergonomic than wrapping the strings in another type.
> `Either AddressParseError ValidAddress`
Real world procedures usually involves many steps which can fail in many ways. The HM type system does not have subtypes. To stuff all possible failures into the `Left` case of `Either` you have to wrap all possible failure types into a sum type, possibly with multiple layers of nesting (huge PITA).
> concurrent Haskell
For all the hassle with the IO monad, you cannot offload your understanding of memory model to the compiler when you use an `IORef`.
Maybe most your problems are embarrassingly parallel and STM is fast enough for the rest. Maybe.
> exactly encode the effects we want a function to be permitted to perform
> To stuff all possible failures into the `Left` case of `Either` you have to wrap all possible failure types into a sum type, possibly with multiple layers of nesting (huge PITA).
Is this not inherent complexity? Is there some language or approach you believe makes this easier? Does it provide the same or similar correctness?
I said "untagged union" to distinguish it from "tagged union", which is another name for sum types. There are several comments that incorrectly called sum types "union types".
But I don't want to spend any more time near purely functional programmers in my professional life, so I will spend some time to unfairly nitpick the article.
> a lot of the new features ... are either inspired by, or at least more robustly implemented in, Haskell.
This is like some programmers, who don't know much about the history of programming languages, saying Java is stealing features from Kotlin (a language I enjoy). In both cases the inspiration usually comes from ML (a language family which includes OCaml - a language I deeply admire).
Type classes (first implemented in Haskell) are neat though. I heard that Java is considering adopting them.
> Let’s imagine we represented these as plain old strings ... `Theatre String String -- venue name and event name respectively` `checkForSeats :: String -> String -> IO [Seat]`
If your language has named arguments, and sum type cases are records where you have to name your fields, using plain strings is just fine, and probably more ergonomic than wrapping the strings in another type.
> `Either AddressParseError ValidAddress`
Real world procedures usually involves many steps which can fail in many ways. The HM type system does not have subtypes. To stuff all possible failures into the `Left` case of `Either` you have to wrap all possible failure types into a sum type, possibly with multiple layers of nesting (huge PITA).
> concurrent Haskell
For all the hassle with the IO monad, you cannot offload your understanding of memory model to the compiler when you use an `IORef`.
Maybe most your problems are embarrassingly parallel and STM is fast enough for the rest. Maybe.
> exactly encode the effects we want a function to be permitted to perform
https://degoes.net/articles/no-effect-tracking "Effect Tracking Is Commercially Worthless"
See "Tagless-Final Effect-Tracked Java™" for a chuckle.
> small sample program
The `Money` type is monomorphic, and `Functor`s are higher-kinded. You get the error message `Expected kind ‘* -> *’, but ‘Money’ has kind ‘*’`