catnaroek
Joined 13 years ago
Joined 13 years ago
To give a perhaps odious but relatable analogy, a form is a list of questions, but a filled form is not a list of answers - it is a record of answers to the questions in the form.
(Aside: Type checkers essentially see recursive function definitions as applications of a fixed point operator to non-recursive functions. If your function has a rank-1 type but uses polymorphic recursion, the type checker sees it as the application of a rank-2 fixed point operator to a non-recursive function. This is why I see polymorphic recursion as “morally higher-rank polymorphism”, even when the type signatures in your code are ostensibly rank-1 ones. Polymorphic recursion is widely used in Haskell.)
However, IMO, you only need rank-1 polymorphism 95% of the time anyway, so optimizing for the common use case is a good strategy. By far, the main use case for generics is implementing efficient and reasonably reusable data structures and algorithms in a reasonably type-safe way. For this use case, monomorphization and aggressive inlining of small functions are evidently the right things to do. Other uses of generics (say, streaming I/O frameworks) strike me as a lot more questionable.
Relevant paper and talk:
http://www.ccis.northeastern.edu/home/types/publications/gra...
It does. For example, this theory identifies when and how incorrectly designed programming languages fail to enforce abstractions, very much like how the theory of database normalization identifies when and how incorrectly designed database schemata fail to enforce data integrity constraints.
But perhaps what you mean is “it doesn't try to view existing programming languages under an unwarranted positive light”.
The examples given in the article are merely derivatives of ordinary mathematical functions defined by ordinary mathematical expressions - in particular, there are no sequencing, no conditionals and no loops. So why call them “differentiable programs” when you are actually dealing with ordinary differentiable functions from good old 19th century analysis? We need urgent improvements in the intellectual honesty department.
> Variables are immutable by default, globals are not allowed, functions are pure.
This is a huge non-sequitur.
There are other (better!) reasons against cross-language interoperability, though, such as the reduction in static guarantees to an unusable lowest common denominator.
There are many legitimate reasons to dislike Haskell, such as being hard to parse mechanically, but being hard to read is not one of them.
> F# and other languages ML-style syntax are probably the easiest to read.
The syntax of ML's module language is pretty complicated. You cannot look at those “where type” (SML) and “with type” (OCaml) clauses and tell me with a straight face that they were meant to be easy to read. This syntax makes translucent ascription harder to read than it ought to be. It is so bad that many[0] people work around it in various ways, like using the combination of generative datatypes and transparent ascription as a poor man's translucent ascription.
As for F#, I would not call it ML-style, precisely due to the inability to express modular abstraction.
[0] Relative to the size of the ML community, of course.