"I am thinking of a data structure for managing collections of objects. It provides O(1) insert and update operations. It has native hardware support on all modern platforms. It has a long history of use. It's proven, and it's lightning fast.
Unfortunately, support for it in my favourite language, Haskell, appears to be somewhat lacking. There are people that would tell me that it's not needed, that there are other options, that it's bad for parallelism and bad for computer science in general. They say that without it, programs are easier to understand and reason about. Yet, it seems that every time I start to write a program I find myself wanting for it. It's called the store.
The mutable store, that is. I want for real destructive update in a real functional language. I wanted it for long enough that I decided I should take a PhD position and spend the next several years of my life trying to get it."
http://benl.ouroborus.net/papers/thesis/lippmeier-impure-wor...
While I admire him, I think the better solution is to give up Haskell.
For many years I have had a lot of fun with Haskell, doing some NLP, and web stuff with Yesod and Scotty.
However, I am so much more production in a concise dynamic language like Ruby that I am re-evaluating my fondness for Haskell. Also, to a small degree, good IDEs like RubyMine catch some simple errors for you.
I, like Elben Shira, hope for radical new technologies that make me feel like I am developing in Ruby with the safety and speed of Haskell. I am looking forward to the future.
Anyway, code that patches immutable data compiled by GHC behaves much like the plain mutable storage you'd write in C. It may not be always simpler to write (but for complex data, it normally is - and why are you writing so much simple data anyway? is it because of your language limitations?) but is checked by the compiler, what's a great bonus.
https://hackage.haskell.org/package/base-4.8.1.0/docs/Data-I...
https://hackage.haskell.org/package/base-4.7.0.2/docs/Data-S...
"Representing effects in value types is a double edged sword (p. 42). Haskell has fractured into monadic and non-monadic sub-languages (p. 44). Monad transformers produce a layered structure (p. 45)." These are section titles, be sure to read the entire sections which explain in details what the title means.
Ben Lippmeier makes a very good point and is being quoted in full here. Haskell does have issues, and people are trying to fix those issues. If they can be resolved isn't known yet, and the resulting language may be different from Haskell. Haskell is a long way from some pinnacle of perfection, and it is very much not a silver bullet to solving problems. Not that anything in computer software is a silver bullet [1].
Given experienced and disciplined programmers, the type system probably isn't as important. But given the quality of programmers who are using these languages in the real world, a good type system does seem to help.
My personal experience is that Haskell isn't really all that complex - when you stick to the core, it's actually fairly simple, with a small set of well thought out features (compared to Scala, for example, which I love but has a lot of features). Strangely enough, what I find hard when dealing with Haskell is the syntax, because it's so different from all the languages I've been taught or taught myself in the past. That shouldn't be a problem for people that have little to no previous experience and tackle it with a virgin mind.
This is an area where the state-of-the-art in static languages (Haskell, Idris, Agda) falls flat, and I suspect that's why (other than ignorance) we see so many comparisons from Haskell advocates between Haskell and the likes of Python, Ruby, or worse that try to paint dynamic languages as offering only brevity through the omission of type signatures as a major advantage over common static languages--an advantage for which Haskell can largely compensate--while completely ignoring the capabilities more sophisticated dynamic languages offer.
Example of such a language is Java. It's runtime is highly dynamic. Class loaders allow you to create new classes, pre-process bytecode, and many other stuff.
You can even rerun portions of your code after you've modified it (rewind it), something that even Smalltalk never supported.
The JVM is a virtual machine targeted by many languages, some of which are dynamic, and Java isn't a "modern" static language from the standpoint of type theory and provability.
In Pharo Smalltalk, for example, you can pause running code in the debugger and modify it using syntax the language doesn't actually support, and then, in the same runtime, open a class browser and modify the compiler to support the new syntax before finally accepting your changes in the debugger and resuming execution. You can swap every reference to one object with references to another object using become:, effectively swapping the identities of two objects globally at runtime.
Perhaps all of this is possible in Haskell and the like, but it's still to be demonstrated.
> You can even rerun portions of your code after you've modified it (rewind it), something that even Smalltalk never supported.
Smalltalk and Lisp both support this.
Interesting, do you have a few pointers?
This is a formal way to do homoiconicity, and frankly much better than codewalkers and CPS-conversions and similar tricks.
I now think that everything you can do with macros in CL, you can do in Haskell too and it will be cleaner. Another good example are lens and traversals, they are generalizations of generic references such that CL can only envy.
Someone should really rewrite On Lisp and Paradigms of AI in Haskell.. (and also Design Patterns from GoF) I think it would prove this point.
Instead of making a case for "new successful dynamic languages" and why such new ones would emerge, both authors are defending the existing benefits of today's dynamic languages.
Elben Shira is saying that he predicts the next wave of successful languages will have static checking but also look & feel like a "dynamic" one made possible by smarter compiler technologies such as type inferencing. (Maxime Chevalier-Boisvert also mentions the new Crystal language as an example of this.)
If one is itemizing all the great points of Python/Ruby/Javascript, that's orthogonal to what Shira is betting on.
The problem I outline is not that static typing involves additional boilerplate. It's the inherent additional cognitive load it introduces. A smarter compiler isn't going to help you there.
The fallacy of Elben's argument is in the assumption that there will be only advances in the field of static typing.
Meanwhile, people working with dynamic languages are improving their tools at an astonishing pace. For example, working with an editor like Cursive provides many refactoring options you could only expect from a static language a few years ago.
The biggest benefit though comes from interactivity though. Dynamic languages lend themselves extremely well to providing live coding environments. This allows for tools like the REPL and things like Figwheel https://github.com/bhauman/lein-figwheel and this kind workflow will be difficult to match for static languages.
Clojure and its family of language will be a thing of the past in a few years from now (Clojure is not even a thing of the present actually, given its minuscule mind share on the JVM).
People create languages all the time. Some languages (like PHP) were just created for problems that the creators had, not for some overriding empirical reason. Dynamic languages also tend to be easier to make. There's nothing to suggest people will stop creating languages and then adopting them, when they are tailored toward specific problems. Any reasoning as to why they might not appear is hand waving for attention.
This is not a criticism of the language, simply descriptive of its current position. Go, which is substantially larger at the moment from what I can see, is just barely cracking that boundary that I described, and probably still has a good year or two before it's quite there.
Elixir is currently on a good trajectory, but I would definitely be concerned that trying to be a Ruby on top of the Erlang VM is going to make it a non-trivial challenge to get to the next level of usage, precisely because the Ruby space is covered, covered, and covered again with mature, existing languages. This is, again, not a promise from me it can't succeed, indeed I wish it all the best, just a description of its challenges. It is growing rapidly in its little niche but it may have a serious challenge getting to the next level.
And, back on topic, when this came up on Reddit, I'd observe that Elixir is the only dynamically-typed "up-and-coming" language I can think of. Nim is statically-typed. Rust is static. Go is probably on the way out of "up-and-coming" but it's static.
I also observe that all the dynamic languages are all adding static type support, even when the static type support is inevitably compromised by the dynamic portion of the language. In the meantime, I don't see any static language trying to move in a dynamic direction... in fact, many of the static languages are moving to be even more static! The net flow of feature work right now is strongly in the static direction.
Erlang is reliable because it's fault tolerant. The Strong Static Typing camp wants software that is reliable because it is faultless.
Elixir has Erlang's philosophy on the problem. I think most of the wailing and gnashing of teeth is because most languages (even most statically typed ones historically) have just completely punted on the notion of language support for writing software that doesn't fall over in a stiff breeze. The more we build layers of software between humans and their actual goals the more this is going to come to a head.
With so many libraries supporting my development, I usually tend to write much less code using a dynamic language. Also most of the code tends to be isolated with clear interfaces exposed to other parts of the code. Writing tests is simpler too, compared to writing them in dynamic languages.
May be large projects with hundreds of thousands of lines of code, could benefit from statically typed languages. But for majority of the projects (80-20 rule) dynamic languages offer cleaner syntax, simpler coding experience and faster time to market (my opinion).
Solely for syntax, my assertion is that this is just because dynamic languages evolve faster. Because they are easier to build.
E.g. one person can buy the dragon book(s), use parser/lexer libraries, get an AST, and then start an interpreter than just stores objects as maps, and evals things dynamically.
But very few people are going to write a new/novel type system on their weekends.
So that's why, IMO, all the sexy/modern syntax shows up in dynamic languages first, and then takes ~a generation or two to reach static languages, where you need a dedicated team to put the effort into the type system + compiler + expected tool set (IDEs/etc.).
(E.g. see Scala, Kotlin, Rust, etc., which have all, IMO, achieved the "syntax as nice as Ruby" level, but took large teams of people to do it).
I've only reasonable experience with Rust in that list but... no. I've seen enough Scala to get that that's not true, and I know it's not true for Rust.
That's not to say that static languages can't have nice syntax - Crystal is a great example if you'r trying to match Ruby - but I don't think your examples are great.
No, but one can hack an extension to the GHC type system in a weekend. (That's one of the reasons why there are so many.)
With dynamic typing you're much more likely to break things up early precisely because you know you have to keep things in your head.
On the other hand, static typing allows you to just keep adding code and it makes sure that the code will compile and run. However, at some point you end up with a large and complex system that you don't really understand. All you know is that it's self consistent. Understanding what the business logic is doing and why can be quite difficult and the fact that it type checks does little to help you there.
Coincidentally this is the reason that static typing proponents are obsessed with refactoring. Once you realize what mess you got yourself in then you have a ton of code to refactor and there's no way you can keep track of it all in your head.
With a dynamic languages refactoring tends to happen in much shorter cycles and introduces much less cognitive load.
Now, I could just write the logic down as logical statements on paper, and check my code against it... Or I can write the logic down as logical statements on the computer, and have it check my code automatically. Pick your poison.
If you are programming with a language that forces to keep everything in your head, you'll never build big systems.
Having no type annotations, even in highly dynamic languages, leads to lower maintainability. However, some type systems are too complicated, and over-engineered, the best example of which is Haskell (compare it to Agda or Idris, which can do more, but have much much simpler type system).
It's not over-engineered. Making syntax in this way was a design goal. AFAIU, authors of the language thought that when you specify as much as possible in syntax, the code is easier to maintain. That's why it's so popular in enterprise world where code often lives for 10s of years.
I suppose no rationale person believes dynamic language would disappear completely. Also I think both dynamic and statically typed languages exist on a spectrum. It is not very productive to talk in generalized terms like "end of dynamic languages".
I like dynamic languages, especially Python and Clojure. But programming with types is important to get things right, on the correct, formal basis. (I think functional programming is a misnomer, it should really be called algebraic-oriented programming, but I digress.) Once you see how to do it correctly it's perfectly OK to mimic the same abstraction in dynamic language.
For example, when I find it hard to understand Haskell code, it's not because of the type system, it's usually that the compiler is doing too much magic for me (with type classes, and automatically lifting things into monads).
I find that having the types actually makes the code itself easier to understand, because I can ask the compiler (usually through the REPL) to tell me what kind of thing can go where. It makes that kind of information more local.
Language like Haskell forces you to do it. It is more effort, but this effort pays off in getting composability and edge cases right. The end result is not actually harder to understand, it's rather that you did not fully understood the problem in the beginning (by glossing over technical details).
I wonder what Shira counts as "successful"? Popular?
Sigh.