note I'm being deliberately provocative with the above statement to promote discussion, not argument. :-)
note I'm being deliberately provocative with the above statement to promote discussion, not argument. :-)
1. most of the analytics/event-stream processing will be done on the backend anyway
2. If you are picky enough you can do functional programming in js. Reative.js is decent library for processing streams of events.
What screams to use something more haskell-like, is their example of 'Trys', i.e:
class GraphQuery extends Query {
static parse(object: any): Try<GraphQuery> {
return TimeRange.parse(object.over).flatMap((timeRange: TimeRange) => {
return Filter.parse(object.where).flatMap((filter: Option<Filter>) => {
return GroupBy.parse(object.by).flatMap((groupBy: Option<GroupBy>) => {
return new Success(new GraphQuery(
filter,
groupBy,
timeRange
));
});
});
});
}
}
should look like something like: parse : Any -> Try GraphQuery
parse object = do
timeRange <- TimeRange.parse object.over
filter <- Filter.parse object.where
groupBy <- GroupBy.parse object.by
return (createGraphQuery filter groupBy timeRange)
(haven't used haskell in quite some time, so maybe I am missing something)For the purposes of this article, we tried to avoid too much syntax sugar to make it more accessible. That aside, I'd love to add something like this to monapt![1].
class GraphQuery extends Query {
static parse(object: any): Try<GraphQuery> {
return TimeRange.parse(object.over)
.combinedWith(() => Filter.parse(object.where) )
.combinedWith(() => GroupBy.parse(object.by) )
.withCombinedValues((timeRange, filter, groupBy) => {
return new Success(new GraphQuery(filter, groupBy, timeRange));
});
}
}
In this design, `combinedWith` is a lot like `then` when using promises. It’s a bit more complicated because `then` assumes that arguments are always passed directly from the previous function, so you need special support to store the return value and retrieve them later as arguments.If the type system requires it for some reason, you could add a `.startCombining()` call at the end of the first line within the method, so that `combinedWith` is sure to be possible.
> parse : Any -> Try GraphQuery
> parse object = do
> timeRange <- TimeRange.parse object.over
> filter <- Filter.parse object.where
> groupBy <- GroupBy.parse object.by
> return (createGraphQuery filter groupBy timeRange)
New ECMAScript 2015 Style parse = ({by, over, where}) => {
timeRange = TimeRange.parse(over)
filter = Filter.parse(where)
groupBy = GroupBy.parse(by)
return createGraphQuery(filter, groupBy, timeRange)
}
or parse = ({by, over, where}) =>
createGraphQuery(
Filter.parse(where),
GroupBy.parse(by),
TimeRange.parse(over));
or parse = ({by, over, where}) =>
createGraphQuery(
Filter(where),
GroupBy(by),
TimeRange(over));
or parse = ({by, over, where}) => createGraphQuery( Filter(where), GroupBy(by), TimeRange(over) );
or parse = ({by, over, where}) => c(f(where), g(by), t(over));
and, if you're willing to put a front-end on it: parse = ({b, o, w}) => c(f(w), g(b), t(o));
Of course, I have not provided the definitions of `c`, `f`, `g`, or `t`.You can avoid excessive nesting/flatmapping with some syntax sugar, but it needs to be sufficiently different from normal declarative code.
If you properly define the functions (`c`, `f`, `g`, `t`), you can get the semantics of halted computation on failure. That is essentially what Haskell's `do` notation does.
I love PureScript (and Haskell, FWIW), but it's a huge paradigm shift from CS, TS, or JS.
> Had our first hire start today who applied because we use @elmlang in production. He rocked it!
> PS: still hiring :)
https://twitter.com/rtfeldman/status/656238188961226752
Furthermore, I’ve learned so many languages on the job in my career that I am unsympathetic to companies who refuse to believe that people who have learned programming can continue to learn programming!
[1]: http://www.paulgraham.com/avg.html [2]: http://www.paulgraham.com/pypar.html
For example, I could imagine easily being able to hire devs to work on Go, but it'd probably be really hard to get them to work on Haskell.
Can you prove that? Absence of evidence isn’t evidence of absence, after all. You’re being a bit militant in your pg-atheism.
Okay, in all seriousness, you are correct. Ability to hire coders to work in a particular language is a legitimate concern to have. Still, it’s sad to see lack of usage drive, well, lack of usage – sometimes it looks to me like an unexamined assumption, or a self-fulfilling prophecy. To take it back to the land of religious arguments: it’s a bit cargo-culty.
New languages can outweigh low popularity with lots of other important qualities: syntax, tooling, appropriateness for a certain purpose, abundance of libraries, etc. If the new language is easy to learn, that pretty much defeats the issue of low popularity all together!
Unfortunately, a lot of new/amazing languages with great tooling are somewhat hard to learn. Again, Haskell might be a great language, but it's daunting to people who only have experience with C-like languages.
Go is one of the exceptions, and I think it did that intentionally. Instead of having complex syntax, it just has lots of boilerplate. It's easier to read and easier to learn at the expense of being harder to write and harder to modify.
How?
> If the new language is easy to learn, that pretty much defeats the issue of low popularity all together!
If the language is easy to learn it's probably not worth learning. "Easy to learn" in most contexts and for most people means "similar" or "familiar".
Of course, there are languages truly easy to learn thanks to their small surface and internal consistency (like Erlang, PicoLisp, Forth...) but they are very rarely regarded as such.
> Again, Haskell might be a great language, but it's daunting to people who only have experience with C-like languages.
My opinion is that it's their problem, not Haskell's. Instead of "being daunted" they should go polyglot already and stop whining.
> How?
By "new" I didn't necessarily brand new. I meant something like Rust, Go, or Julia. They're more than 3 years old and relatively fully-baked, but they're much younger than the mainstream languages.
I don't know much about Julia, but in the Rust and Go communities, the early adopters are producing libraries for the not-so-early adopters. A good question would be, "Why?" I think the answers are: 1) fun, 2) because they want to get others to use the language, and 3) because their company has adopted the language in production.
So it does (and has to) happen. In this whole thread, I'm not talking about the decision-making process of an early adopter. I'm talking more about someone replacing a mainstream language in a production or business environment.
> "Easy to learn" in most contexts and for most people means "similar" or "familiar".
I meant "easy to learn" however you want to define that. Similar/familiar is fine, as it's definitely contributing to the popularity of Rust and Go. It really does hurt some excellent languages (e.g. OCaml) that they look so alien to mainstream, working programmers.
> My opinion is that it's their problem, not Haskell's
That's true. A language should have whatever syntax is most effective and not make the same mistakes that past languages made.
However, that's not the same thing as readability. A language can be totally different from C-family languages and still be readable. To mention OCaml again, I find it ridiculously hard to read because there are tiny, similar-looking characters that are significant all over the place. To my eye, significant dots and tildes are very hard to pick out when I'm scanning down a page.
So assuming Haskell is readable to a complete newbie, it isn't Haskell's problem that the syntax is new. But it is Haskell's problem if it can't overcome the catch-22 that people don't use a language if other people don't use it.
I'm glad we're talking about Haskell, because that community is very enthusiastic and has made some incredible, accessible Haskell resources to solve this problem. It may not be their problem, but they're still attacking it, as every language has to. It seems to me that the Rust community knows this and is going in the same direction with highly-accessible tutorials.
As for Go, the language is so small that it's "easy to learn" in terms of syntax, but the patterns and paradigms you use in Go might take longer as a result.
How will you explain a relative success of F#, then?
In my opinion "looking alien" is not important at all. To the mainstream real qualities are much less important than marketing; that's true in many areas and mainstream programming is not an exception. Given enough marketing, you can turn "alien syntax" into a perceived advantage relatively easily.
> To mention OCaml again, I find it ridiculously hard to read because there are tiny, similar-looking characters that are significant all over the place.
Have you seen J? I'll just paste a bit of code in it:
join =: 1 : 0
((([:{.[:>{.),:[:([:<(>"0))"1[:{:[:1 2 0&|:[:>([:,u"0)#]) (pr y))
)
Is it readable? I'm told that yes, it is. There are people who can read this mess just fine, no problems at all.Readability is an artifact of familiarity and, in some cases, tooling. You can get used to reading (and writing) even the most "unreadable" of syntaxes. Ask a PERL programmer if she finds her language readable. Will she say "no"?
My point is: until readability is formally defined and we're able to measure it objectively it's utterly useless to talk about it.
> But it is Haskell's problem if it can't overcome the catch-22 that people don't use a language if other people don't use it.
Yes, but this problem cannot be solved with technical qualities alone. Was it possible we wouldn't use C, Java or JavaScript at all.
It's marketing and "killer use-cases" that matter. You want to use the same language your OS is written in, for example. Was Windows written in OCaml you'd use OCaml to write Windows programs. If there's a program you really like, which is scriptable in Lua, you will use Lua.
It's more defined than we, as programmers, pretend it is. There's research in cognitive psychology, linguistics, and lexicology that tells us that some things are easier for human brains to process than others.
For example, if you skim through a block of code, it's easier to pick out "&&" than it is to pick out "and". There are lots of rules like this.
This is partially because of the way humans read words. If yuo spel a bunhc of words wrng in a sentence in minor ways that don't alter the shapes too much, it's still very readable.
That's why your example of J is very hard to read (objectively, not relatively). If someone removed or altered a few of those symbols, no one would notice upon skimming it. It's ludicrous to argue that it's readable just because some people say it is (and I think they're just bragging to begin with).
I'm not convinced that such research controls for familiarity effects. Not to mention, programming languages have much richer syntaxes than natural languages. I think (suspect), in regard to PLs, what you're talking about (you mention "skimming" later) is actually legibility - ease of recognizing letters and words. Not readability, that is ease of understanding the meaning of what's written.
> For example, if you skim through a block of code, it's easier to pick out "&&" than it is to pick out "and".
Why? What if the rest of the line is similarly composed of punctuation? Are you sure in a line looking like this:
>&.@:/"1\and[: NB. some nonsensical J phrase
you'd have an easier time spotting the "and" were it written as "&&": >&.@:/"1\&&[:
> If someone removed or altered a few of those symbols, no one would notice upon skimming it.Possibly, but we're not talking about "skimmability", but readability. Removing or altering a few characters in that line would result in an incorrect, nonsensical sentence and you'd notice it right away.
"Right away" is subjective, of course. I spent nearly an hour trying to read this damned thing when I attempted it for the first time. Every J phrase was a challenge then. It's still hard, but it got much easier with practice. The trick here is exactly the same as in your example:
> yuo spel a bunhc of words wrng
that is, once you learn how the words look like you can recognize them easily, even if they are a bit mangled.
> (and I think they're just bragging to begin with)
Yeah, I get the same feeling sometimes ;-)
But a human brain is great at pattern recognition. It has to be trained, and it's possible that some shapes are harder to learn to recognize than others, but once you learned them... is there really a difference?
Learning different PLs is my hobby, I've looked at ~80 languages to date and learned quite a chunk of them. Every single time I noticed this effect: once you internalize shapes of common phrases, you stop having trouble reading the code. It's much, much harder in some case (J is an abomination here - I'm trying to really learn it for the second year now and... it's not going that well) and easier in others (Smalltalk, Lisp, Forth, ...). But I strongly suspect every language, if studied and used enough, becomes readable.
I've been on both sides of Haskell hiring. There's more people who want nice Haskell jobs than Haskell jobs advertised these days.
https://mail.haskell.org/mailman/listinfo/haskell-cafe
http://www.haskellers.com/jobs
http://careers.stackoverflow.com/jobs (more general, but I see Haskell jobs here and look for them here)
There are plenty of developers, especially here on HN, who would absolutely love to work with Clojure/ClojureScript full-time.
1) you'll need less people (better more reusable code) 2) the best people will speak you out.
This was very much my experience when I put a Haskell team together, and everyone I've spoken to who has done the same has said the same.
It's an opportunity for a young company, not a problem.
On the one hand there's a smaller pool of people, on the other hand a primary issue in hiring is sifting people who can do the job from a random draw[0], in which case interest and/or knowledge of Elm or Purescript is a huge prefilter, and can draw/poach people who wouldn't otherwise be interested (pg's "the python paradox"[1] talks about that)
[0] or worse, you don't get a random section of developers, you get a section of developers currently looking for a job, so the average competence of your draft is below average.
As opposed to what? In what ways do you not consider Javascript to a be a functional language?
var a = 1;
a = 2;
window.someGlobal = 'foo'; const a = {b: "foo"};
a.b = "bar"; const a = icepick.freeze({b: "foo"});
Granted, that's not as elegant as built-in support but that is literally what I'm doing at the moment when I want immutability.All a functional language really needs is first class functions. JS has had that since the very beginning.
* Pure functions - JS functions are essentially subroutines. They might return a useful value or they might mutate a bunch of stuff and interact with the outside world. Who knows? JS functions aren't guarunteed to return the same value, or any value at all.
* Immutability - Anything and everything can be mutated in JS, including the contents of objects that are defined using the new ES6 `const` keyword
* Curried functions by default - Although it's possible to compose or partially apply JS functions, it's not nearly as nice as Haskell or Elm.
* pure functions - all you said is equally true for Scheme
* immutability - set-cdr! and many SRFIs: vectors, boxes, records...
* curried by default - nope, not in Scheme either
There are other flavours of FP languages other than ML descendants. They are not "less functional" at all.I mean, it seems pretty useless to define "functional programming language" in a way that includes both C and OCaml just because you can pass functions around in both of them.