From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 10.50.22.98 with SMTP id c2mr490938igf.0.1447669515251; Mon, 16 Nov 2015 02:25:15 -0800 (PST) X-Received: by 10.182.87.132 with SMTP id ay4mr123511obb.14.1447669515170; Mon, 16 Nov 2015 02:25:15 -0800 (PST) Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!mx02.eternal-september.org!feeder.eternal-september.org!au2pb.net!usenet.blueworldhosting.com!feeder01.blueworldhosting.com!border2.nntp.dca1.giganews.com!border1.nntp.dca1.giganews.com!nntp.giganews.com!i2no3870622igv.0!news-out.google.com!l1ni6138igd.0!nntp.google.com!i2no3870618igv.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Mon, 16 Nov 2015 02:25:14 -0800 (PST) In-Reply-To: Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=82.216.245.129; posting-account=21X1fwoAAABfSGdxRzzAXr3Ux_KE3tHr NNTP-Posting-Host: 82.216.245.129 References: User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <14533506-4289-4148-b8c4-e970f5778b26@googlegroups.com> Subject: Re: Haskell, anyone? From: Hadrien Grasland Injection-Date: Mon, 16 Nov 2015 10:25:15 +0000 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Xref: news.eternal-september.org comp.lang.ada:28398 Date: 2015-11-16T02:25:14-08:00 List-Id: Le dimanche 15 novembre 2015 21:42:27 UTC+1, mockturtle a =E9crit=A0: > Dear all, > I recently read in the Italian version of Linux Format an interview to Ka= tie Miller. It got me intrigued the fact that when she talks about Haskell= , she says things that usually Ada enthusiasts say about Ada ("when it comp= iles, it runs...", "the number of bugs is reduced..."). I remembered that = some time ago I met someone that was enthusiast both about Ada and Haskell = (when I said that I program in Ada, he said something "Finally! Now I need= to find someone who likes Haskell." >=20 > The question should be obvious: it seems that Haskell and Ada would attra= ct the same kind of person; does someone here know and like Haskell as well= ? >=20 > Riccardo *** Rant warning, all FP fans please close your eyes for a second *** I've been learning OCaml, a close cousin of Haskell, for about a month now,= in an attempt to better understand functional programming's principles, be= nefits and drawbacks. Here are my thoughts so far : Functional programming is based on the core tenet that mutable state is evi= l and should be obliterated. Indeed, in doing so, functional programming pr= oponents make some good point : mutable state makes programs less predictab= le, less testable, and harder to understand. And by eliminating mutable sta= te, functional programming also puts an end to an endless quarrel between p= rogrammers and mathematicians about the meaning of the "=3D" sign. Now, that's for the theory. In practice, eliminating state also has strong = negative consequences. For one thing, all useful programs have state. If a = program does not display anything on the screen, does not write to any file= , and in general does not command any external peripheral to *change state*= , it is effectively a useless program which wastes CPU cycles for no good p= urpose. This means that in practice, all functional programmings always mak= e some compromises in their war against mutable state. Typical abstractions= include putting an imperative programming backdoor somewhere in the langua= ge, as in OCaml, or adding some abstract and opaque "state" type that funct= ions take as a parameter and return as an abstract result. =3D=3D=3D=3D=3D=3D A second problem with programming without mutable state is that if you cann= ot change your state, you will have to duplicate it, sometimes a lot. For e= xample, consider a pseudo code which computes a running average : "For all i such that 2 < i < N - 1, B[i] =3D A[i - 1] + A[i] + A[i + 1]" Unless your programming language provides syntactic sugar for this specific= scenario, you will have to fill in B's elements one by one. But because fu= nctional programs cannot change B once they have assigned a value to it, yo= u will need to create a whole lot of copies of B, each with one element cha= nged with respect to the previous one : - A copy of B with its first element set - A copy of B with its first and second element set - A copy of B with its first, second and third element set - and so on... If B is big, this means a whole lot of memory traffic, and thus pretty awfu= l performance. Unless, that is, the compiler is clever enough to optimize t= he copies out and effectively produce an imperative program. Which leads us= to the second core tenet of functional programming : "The compiler and the= user are both clever enough". This one is very strong, and is not without = reminding the usual rethoric of C programmers : "If the user hits himself i= n the foot with pointers, he's not good enough to handle C". =3D=3D=3D=3D=3D=3D Functional programming language designers' belief that users are genius bec= omes most obvious when one tries to perform simple tasks with these. For ex= ample, let us assume that we have some list of data that we want to display= to the user. In any modern imperative language, this takes one to three ve= ry simple lines of code : "For all elements E of A, display E" In a functional programming program, loops are considered evil, because on = their inside they hide some kind of mutable counter which goes against the = idea of having no mutable state. So instead, you will often be forced to wr= ite something awful like this : "let f : List a -> List =3D .....if a is empty then .........return empty list .....else .........display first element of a .........return f(rest of a)" Notice that this example is long, much more difficult to understand, and ma= kes heavy use of recursion (and thus, assumes that the compiler will be cle= ver enough to optimize it out). And if you have some fun, imagine what the = functional programmer will have to get through if he has to write the "disp= lay" function at some point. Also, I have cheated by using return statements. Functional programming doe= s not have statements, because statements have some underlying mutable stat= e to them (the program counter) and thus originate from the realm of Satan.= To write any complex program in functional programming languages, you are = expected to do everything using expressions. So if you have ever suffered t= he horror of debugging three nested trigraphs in C, imagine how a typical f= unctional programmer feels when he has to debug this : http://benchmarksgame.alioth.debian.org/u64q/program.php?test=3Dpidigits&la= ng=3Dghc&id=3D4 =3D=3D=3D=3D=3D=3D In short, functional programming produces write-only code that pleases math= ematicians and puts a lot of pressure on compiler writers. This classifies = it as a programming style which is very much squarely aimed at people from = academia. What about the claim that functional programs are always correct = ? In a further attempt to please code aesthetes, functional programming langu= ages have very elaborate type inference systems, which are heavily (ab)used= by most practitioners. The idea is that you should not have to repeat your= self by writing types over and over again if you already know them. Also, a= type inference fan will add, this means that your programs will always get= genericity for free : a program which adds floats, will probably also work= with ints, and so on. But there is a price to pay for type inference. And to understand which pri= ce, we have to look no further than the most successful implementation of t= ype inference worldwide, C++ templates. Whenever someone passes the wrong parameter to a C++ template library, that= person is inundated by a wall of compiler diagnostics, sometimes thousands= of lines long, and full of library implementation details. The reason why = this is the case is that because type inference is used througout the whole= code hierarchy, compilers can only detect errors at the very bottom of it.= The error then needs to bubble up the code and module hierarchy, accumulat= ing an enormous amount of diagnostic noise along the way. Decades of experience with full type inference suggest that it will always = break software abstractions and result in incomprehensible compiler diagnos= tics, no matter how it is implemented. Which is why even the C++ people are= now shifting away from it, adding some extra layers of type check to templ= ates in a future version of the standard with "concepts". It sounds like functional programmers still have that lesson to learn, howe= ver, as even though many FP languages support type annotations, I have yet = to encounter real-world functional programs which take the time to use them= properly. =3D=3D=3D=3D=3D=3D Even when you have manage to get through unreadable compiler diagnostics an= d broken software abstractions, even when you do get a functional program w= ith type inference to compile, you still are far from having perfect assura= nce that your program is incorrect. In fact, because your program is barely= readable, as outlined above, you cannot even check it on a basic way by re= ading through it manually. The great thing about FP, though, is that the resulting program will be muc= h easier to test, precisely because it has little to no mutable state. But = I'm not sure if all the pain you have to go through in order to reach this = point is worth it. =3D=3D=3D=3D=3D=3D Now, of course, as I mentioned on top, this post is rantish and I have made= a couple of important simplifications. For example, I have ignored a very = important piece of syntaxic sugar featured by most functional programming l= anguages, the list comprehension. A typical list comprehension which filters integer elements according to so= me criterion, then returns their successor, would look like this : "[ FOR ALL elem IN source_list WITH filter(elem) DO elem + 1 ]" Like any data-parallel abstraction, this programming language feature is ve= ry nice to use, and will result most of the time in code being simpler and = the compiler doing the right thing. However, this only works for simple cod= e that fits within the list comprehension's programming model, which is usu= ally fairly limited. This is why I classify this feature as syntaxic sugar = : it is usually not designed for maximum power, only for occasional conveni= ence. For example, my running average example couldn't be implemented with the li= st comprehension syntax above, because it is a gather operation, and not a = map operation (it accesses multiple source indices). Few functional program= ming languages in the wild feature list comprehensions that support gather = operations. So, don't only read my somewhat negative opinion, nor that of the Haskell z= ealots who will try to handwave away all the problems of the functional pro= gramming model. Read many arguments and counter-arguments, try it yourself,= see how you like it, which problems it fits best, and so on. This is progr= amming we're talking about, after all :)