Re: [scala-language] The cake’s problem, dotty des ign and the approach to modularity.
Shelby <[email protected]>
| Newsgroups | gmane.comp.lang.scala |
|---|---|
| Message-ID | <[email protected]> |
Coming back to this ... and sorry no time to construct a blog too rushed ... To summarize ideas against premature specialization (not claiming these are original ideas): 1. Don't use subclassing, i.e. don't implement any method in a supertype (e.g. `trait`) that isn't `final`, thus all methods are final (closed) in their existential type[1]. 2. Subtyping should only be injected locally at the call site with inversion-of-control (c.f. my ideas upthread for potential new forms of compiler assistance), or globally due to the Liskov Substitution Principle resulting from type constructors of kind >= 0 (a.k.a. type parametrization) and first-class functions (a.k.a. functional programming, i.e. functions can evaluate and return functions). 3. Functional programming is differentiated from imperative programming in that the semantics are expressed more unified (atomically, i.e. higher-level) — of which premature specialization employing discarded semantics[2] (which includes unrolling function recursion replaced with loops and mutable variables), mutable variables[3], or referential opaqueness are egregious cases. Category theory can raise this up another level. Several resources[1][4] seems to confirm the criticism that Scala while being high-level, introduces more complexity than Haskell. Most of the aforementioned premature specializations Haskell makes difficult to introduce (which the Scala programmer could choose to avoid but isn't discouraged from doing so), except apparently Haskell can't do the implicit global subtyping due to LSP (in #2)—such as adding elements of different types to a list—because refinement types are impossible due to bottom populating all types, i.e. Haskell can't do the new injunction and disjunction types of the DOT calculus (Dotty)![5] Other than highly discouraging premature specializations and the universal type inference due to the lack of availability of subtyping—being by default pure, lazy, total, memoized—Haskell can elegantly express coinductive or infinite constructs (e.g. `fib 0 = 0; fib 1 = 1; fib n = fib (n-1) + fib (n-2)`) which can also be expressed more verbosely with obscured semantics (i.e. more imperatively) in the by default impure, eager, strict, non-memoized Scala[6]. Also laziness provides a performance advantage for functional composition[7]. Laziness introduces timing indeterminism at runtime. Totality makes non-termination (Haskell's `undefined` value synonymous to Scala's `Nothing` type) a value (not a type) and its type bottom _|_ is at top of the hierarchy of inductive types[8], thus an exception when using a value can occur at runtime far removed from the source of the non-termination (another form of indeterminism). It also has deeper negative implications that I don't completely grasp[9]. Haskell's pure, lazy, totality can be selectively disabled but more verbosely with obscured semantics. So comparing the two, what one taketh then other giveth and vice versa. Except apparently the lack of subtyping (refinement types) in Haskell is a major weakness (even after we remove subclassing, which is an anti-pattern) which means DOT (Dotty) could potentially take a big leap ahead? Is this paucity the price paid for Haskell's revered brevity? [1] https://existentialtype.wordpress.com/2011/03/16/what-is-a-functional-language/ "5. It should have a rich type structure that permits introduction of new abstract types and which supports modular program development. By giving short shrift to expressions and evaluation, imperative language have an impoverished notion of type—and not support for modularity. Worse, object-oriented programming, a species of imperative programming, is fundamentally antimodular because of the absurd emphasis on inheritance and the reliance on class-based organizations in which functionality metastasizes throughout a program." http://tonymorris.github.io/blog/posts/what-kind-of-things-are-easy-in-haskell-and-hard-in-scala-and-vice-versa/index.html "Scala also has the ability to namespace a function by giving special status to one of its arguments (some people call this OO, then don’t, in the very next breath – I never get it). What I mean is, you may have two functions with the same name, which are disambiguated at the call site by the type of the argument to the left of the dot. I am deliberately not calling this by any special name, but rather focussing on its utility – Haskell can do this with qualified imports – not quite so nice. I am usually, though not always, particularly unimaginative when it comes to inventing function names – allowing me to reuse one without a penalty is very handy indeed. Note here I do not mean overloading – I think the Scala community has worked out that overloading is just not worth it – do not do it, ever." [2] https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/ "I must associate a provenance with that bit in order to give it meaning. “This bit being true means that e and e’ are equal, whereas this other bit being false means that some other two expressions are not equal.” Keeping track of this information (or attempting to recover it using any number of program analysis techniques) is notoriously difficult. The only thing you can do with a bit is to branch on it, and pretty soon you’re lost in a thicket of if-the-else’s, and you lose track of what’s what. Evolve the program a little, and you’re soon out to sea, and find yourself in need of sat solvers to figure out what the hell is going on." "It’s just that Boolean thinking has infected the software world to such an extent that I feel that I have to fight back. Just the idea of comparison to “null” to obtain a Boolean is absurd, even if you think you need a “null” pointer (which you don’t, in a properly designed language)." [3] https://existentialtype.wordpress.com/2011/03/16/what-is-a-functional-language/ "2. It should support both computation by evaluation and computation by execution. Evaluation is a smooth generalization of high school- and university-level mathematics, and is defined in terms of standard mathematical concepts such as tuples, functions, numbers, and so forth. Variables are given meaning by substitution, and evaluation consists of simplifying expressions. Execution is the action of a program on another agent or data structure conceived of as existing independently of the program itself. The data lives “over there” and the program “over here” diddles that data. Assignables (my word for what in imperative languges are wrongly called variables) are given meaning by get and put operations (fetch and store), not by substitution. Execution consists of performing these operations." [4] http://hammerprinciple.com/therighttool http://joshbassett.info/2013/hello-haskell-goodbye-scala/ http://blog.samibadawi.com/2013/02/scala-vs-haskell-vs-python.html http://jnordenberg.blogspot.com/2012/05/my-take-on-haskell-vs-scala.html http://blog.srinivasan.biz/software/if-you-have-to-learn-just-one-programming-language http://tonymorris.github.io/blog/posts/what-kind-of-things-are-easy-in-haskell-and-hard-in-scala-and-vice-versa/index.html "These tools exist and are as useful as they are, because of certain fundamental properties of Haskell itself. Here I mean, the hoogle function is only as useful as it is because Haskell tags IO effects in the type delineating values with types IO t and t, so hoogling for say, [a] -> Int eliminates a lot of candidate functions that would have this type in other environments. In Scala, without the delineation between an Int that has been computed with its arguments, and an Int that has been computed with the entire universe, a hoogle-equivalent would not be as useful" [5] https://www.reddit.com/r/haskell/comments/3aqj67/in_what_ways_does_haskell_support_intersection/ [6] arr(0) = 0; arr(1) = 1; def fib(n: Int): Int = if (n <= 1) n else if (n - 1 >= arr.length) fib(n - 1); arr(n) = arr(n - 1) + arr(n - 2) } // complication of array upsizing not shown [7] http://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-in.html [8] https://existentialtype.wordpress.com/2011/04/24/the-real-point-of-laziness/#comment-770 [9] https://wiki.haskell.org/Hask#Hask_is_not_Cartesian_closed -- You received this message because you are subscribed to the Google Groups "scala-language" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.