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.182.68.113 with SMTP id v17mr423511obt.2.1447839892133; Wed, 18 Nov 2015 01:44:52 -0800 (PST) X-Received: by 10.182.44.169 with SMTP id f9mr6376obm.16.1447839892097; Wed, 18 Nov 2015 01:44:52 -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!usenet.blueworldhosting.com!feeder01.blueworldhosting.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!i2no4614138igv.0!news-out.google.com!l1ni1306igd.0!nntp.google.com!i2no4614137igv.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Wed, 18 Nov 2015 01:44:51 -0800 (PST) In-Reply-To: <871tbocgjw.fsf@nightsong.com> 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: <14533506-4289-4148-b8c4-e970f5778b26@googlegroups.com> <87si45msuz.fsf@nightsong.com> <35d6dc4f-4f2e-4e75-925c-e4acc7c8f112@googlegroups.com> <871tbocgjw.fsf@nightsong.com> User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <420eb44b-3d33-437f-b846-4c96057e92e5@googlegroups.com> Subject: Re: Haskell, anyone? From: Hadrien Grasland Injection-Date: Wed, 18 Nov 2015 09:44:52 +0000 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Xref: news.eternal-september.org comp.lang.ada:28439 Date: 2015-11-18T01:44:51-08:00 List-Id: Le mercredi 18 novembre 2015 01:11:38 UTC+1, Paul Rubin a =E9crit=A0: > > As I said before, even if I've been regularly trying > > to understand the intricacies of FP for about a year now, it's the > > longest-lasting continuous attempt so far, and it's only been a > > month. >=20 > You should probably look at Hughes' paper "Why FP matters" if you > haven't: >=20 > http://www.cse.chalmers.se/~rjmh/Papers/whyfp.html See my reply to your other post. My conclusion so far (which has no pretens= e of being final, of course) is that there are benefits to the functional a= pproach, but that said benefits won't come for free. You get more code reuse from polymorphic higher-order functions, you pay by= increasing your abstractions' sophistication and thus making the life of n= ewcomers harder (and in general making your code harder to read even by exp= erienced people). You use more powerful data structures (lists), you pay by losing constant-t= ime random access, efficient memory usage, and cache locality. You get the problems of mutable variables out of the way, you pay by extra = complexity in problems which this abstraction adresses well. You get conceptually infinite data structures (lazy evaluation), you pay wi= th largely unpredictable run-time behavior (in terms of memory consumption,= CPU usage, and error locality). You free yourself from the pain of manual memory management, you get bitten= back by it when your program ends up consuming massive amounts RAM, trashi= ng all caches on the system, and when a train fails to brake because it was= busy reclaiming memory instead of answering the driver's commands. Programming is about tradeoffs, which is why no single programming language= can be universally classified as better than the other. Myself, I'm curiou= s about learning new sets of tradeoffs, so as to expand the set of problems= which I can solve efficiently as a programmer. But here too there's a tradeoff: with much programmer curiosity comes much = learning pain :) > > I have already grasped that getting it right is going to take a lot > > more time. >=20 > I don't know, it's not really harder than other types of programming, > just different. >From a usability point of view, different is hard. I know, that's unfair. E= veryone who tries to do something new hates this statement. But it doesn't = make it less true. If you're proposing something new, it better have enormo= us benefits to compensate for the learning pain. > > If the goal were to only use side-effects *sparingly*, I believe that > > all skilled imperative programmers already do that really. ... > > - Global variables are to be used with extreme caution >=20 > Except that the external world (that i/o interacts with) is in essence a > giant global variable. One thing I learned from Haskell is the value of > putting all the i/o in the outer layer of a program rather than > scattering it through everything. Writing functions to have no side > effects (like IO, or old-fashioned stateful OOP) when possible is > another angle on avoiding global variables. >=20 > > - Variable reuse is a terrible idea, their scope should be reduced > > instead >=20 > Sure, like using recursion instead of loops with mutating indexes. >=20 > > - If something can be const, it should really be >=20 > Example: instead of using mutable maps like hash tables, FP prefers > mutation-free balanced trees, etc. The Chris Okasaki book that Mark > Carroll mentioned is all about this topic. Again, I agree that functional programming takes these imperative programmi= ng best practices further. What I am saying is that imperative programmers = already know about them, but stop at a certain sweet spot of optimization b= eyond which the price to pay for immutability becomes heavier :) > > The difference, as far as I can see it, is that the philosophy of > > functional programming is to hunt mutable variables and effects much > > further, sometimes I would say far beyond the point of diminishing > > returns. >=20 > I think with the right tools, the FP style leads to quicker and safer > development, if you don't mind the performance hit. If you look at some > low level Haskell libraries, they do use mutation and other ugly tricks > to maximize speed. That lets higher-level application code get the > performance gains while leaving the libraries to deal with the dirt. > The libraries *could* (mostly) be written in pure FP style and they'd > work fine, they'd just be slower. Quantify the importance of "quicker development", though. Many programs spe= nd a lot more time being maintained than being written for the first time. = At this point, I am not yet convinced yet that functional programming langu= ages have fully taken into accound the importance of this fact. That is not a concern for all programs, though, and I agree that for exampl= e it could make FP languages more fun for write-and-forget codebases like p= rototypes and hackathons. Tradeoffs and "it depends on your project", as us= ual, I guess. > Oh, that was the notorious "monad tutorial" era. We're over that now > ;-). See: >=20 > https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-mo= nad-tutorial-fallacy/ >=20 > If you take a math class you have to learn some stuff. People shouldn't > expect skillful programming to be different. That is true, however there is also a benefit in staying away from complex = and powerful mathematical abstractions unless you truly need to use them. I= t frees your mental resource in order to better focus on the problem you're= solving. For example, I know that the sets of rational numbers and polynomials are b= oth rings. This powerful mathematical abstraction has been recorded into my= head at some point in my studies. But thankfully, I don't need to remind m= yself of this fact anytime I need to use a rational fraction or a polynomia= l in my computations. I also know all there is to know about Hilbert spaces, the Gram-Schmidt ort= honormalization algorithm, and the difference between Gauss' pivot and LU d= ecomposition. But I don't need that knowledge to do linear algebra everyday= , since people more skilled than me have built powerful computation tools a= nd libraries, which will pick the right algorithm for me most of the time, = and otherwise explain me the trade-off between different approaches in simp= le words within their documentation. I believe that programming languages should be the same: sure, it's best if= they are built on top of a very solid mathematical background, that many c= lever people have spent a lot of time elaborating over hundreds of years. B= ut I shouldn't need to care about all of that in order to *use* the stuff. = When low-level details (mathematics) leak into a high-level abstraction (pr= ogramming languages), it is somewhat problematic in my opinion. > > This sounds like an attitude I am more likely to get behind: know many > > tools, and pick the right tool for the right job. >=20 > Actually it's a reason to pick Haskell for your learning experience, > because you get to understand FP a lot better, instead of something > that's half-FP half-imperative. At that point Ocaml becomes easy. I > haven't used Ocaml but have looked at the docs and it has much less > learning curve than Haskell. It's basically Lisp with a type system. >=20 > Looking at it another way, say you're coming from a highly abstract > background like Haskell and you want to try some low level programming > to find out how computers would really work. Does that mean study Ada? > IMHO it means study assembler and move to Ada from there. Conceptually, I could agree with you, but practically speaking, impedance m= ismatch is also an issue. If you try to learn too many new concepts in too = little time, your brain blacks out and you hit a wall. That pretty much sum= s up my previous experiences with FP. This is not to say that I won't give Haskell another try later on. After al= l, I all but have it as my goal to give every reasonably popular programmin= g language a try at least once in my life. But for now, I'm afraid I need s= omething simpler to understand :) > > The main reasons why Ada is so verbose is that asks you to be quite > > specific about everything you do (which is good for debugging, because > > it means the compiler and runtime can catch more errors) >=20 > Meh, it mostly means there's more places for your code to go wrong. If > the compiler is already debugged and can figure stuff out so you don't > have to, you're better off. Think of the Ada compiler doing things like > register allocation for you. Haskell just takes that to another level. I disagree, and in fact I think even functional programmers can understand = why extra verbosity sometimes helps with static code checking because I jus= t saw an example of it in my OCaml classes recently. Consider this : "type Euro =3D float ;; type Dollar =3D float ;; let five_euros =3D 5. ;; let five_dollars =3D 5. ;; let silly_idea =3D five_euros + five_dollars" And compare it to this : "type Money =3D | Euro of float | Dollar of float ;; let five_euros =3D Euro 5. ;; let five_dollars =3D Dollar 5. ;; let silly_idea =3D five_euros + five_dollars ;;" Given one simple change to the type hierarchy and a bit of extra verbosity = in every let-binding, a code which did something absolutely rubbish has tur= ned from an error which could only be detected at run time to a static comp= ile-time error. This is the Ada philosophy in a nutshell : given precise enough type and fu= nction definitions, error detection can often be pushed from testing to run= -time, and sometimes from run-time to compile-time as well. I believe that = it is a philosophical standpoint which Ada and most modern functional progr= amming languages have in common, although the precise implementation detail= s will differ. > > Just the other day, I encountered a C++ problem where passing a > > closure as a parameter to a function was the right thing to do... I'm > > not sure I would have thought about that if it weren't for all my past > > attempts at learning FP. >=20 > Yes, C++11 got closures and std::shared_ptr is a poor man's garbage > collection. It's getting more like Haskell every day ;-). Just a nitpick which I'm sure you are already aware of, but shared_ptr is r= eference counting, not garbage collection. This means that it comes with a = somewhat different set of tradeoffs. Advantages of reference counting: - Garbage collection can only manage dynamically allocated memory, whereas = reference counting can easily handle any kind of resource - Reference counted programs are a lot more deterministic, and thus easier = to reason about and debug - In general, garbage collection tends to be a lot more wasteful in terms o= f memory usage Advantages of garbage collection: - Due to economics of scale, garbage collection usually comes with a signif= icantly reduced CPU overhead - It is easier to deal with some tricky scenarii like cyclic references whe= n using garbage collection > > So far, I have the impression that what I dislike about functional > > programming is the obsession of absolute functional purity beyond the > > limit of practicality,=20 >=20 > I think if you're trying to learn a new subject, it's better to do it > with a feeling of open exploration and discovery, rather than pursuit of > a specific end result. So don't worry too much about practicality until > you know the landscape. There are amazing things you might never have > thought of, that you could end up bypassing by staying on too narrow a > track. Heh, again, learning comes with its pains, but I wouldn't do it if it weren= 't also quite rewarding in the end :)