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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.