comp.lang.ada
 help / color / mirror / Atom feed
From: Hadrien Grasland <hadrien.grasland@gmail.com>
Subject: Re: Haskell, anyone?
Date: Wed, 18 Nov 2015 01:44:51 -0800 (PST)
Date: 2015-11-18T01:44:51-08:00	[thread overview]
Message-ID: <420eb44b-3d33-437f-b846-4c96057e92e5@googlegroups.com> (raw)
In-Reply-To: <871tbocgjw.fsf@nightsong.com>

Le mercredi 18 novembre 2015 01:11:38 UTC+1, Paul Rubin a écrit :
> > 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.
> 
> You should probably look at Hughes' paper "Why FP matters" if you
> haven't:
> 
> http://www.cse.chalmers.se/~rjmh/Papers/whyfp.html

See my reply to your other post. My conclusion so far (which has no pretense of being final, of course) is that there are benefits to the functional approach, 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 newcomers harder (and in general making your code harder to read even by experienced people).

You use more powerful data structures (lists), you pay by losing constant-time 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 with 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, trashing 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 curious 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.
> 
> 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. Everyone 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 enormous 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
> 
> 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.
> 
> > - Variable reuse is a terrible idea, their scope should be reduced
> > instead
> 
> Sure, like using recursion instead of loops with mutating indexes.
> 
> > - If something can be const, it should really be
> 
> 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 programming best practices further. What I am saying is that imperative programmers already know about them, but stop at a certain sweet spot of optimization beyond 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.
> 
> 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 spend 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 languages have fully taken into accound the importance of this fact.

That is not a concern for all programs, though, and I agree that for example it could make FP languages more fun for write-and-forget codebases like prototypes and hackathons. Tradeoffs and "it depends on your project", as usual, I guess.


> Oh, that was the notorious "monad tutorial" era.  We're over that now
> ;-).  See:
> 
> https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/
> 
> 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. It 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 both 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 myself of this fact anytime I need to use a rational fraction or a polynomial in my computations.

I also know all there is to know about Hilbert spaces, the Gram-Schmidt orthonormalization algorithm, and the difference between Gauss' pivot and LU decomposition. But I don't need that knowledge to do linear algebra everyday, since people more skilled than me have built powerful computation tools and libraries, which will pick the right algorithm for me most of the time, and otherwise explain me the trade-off between different approaches in simple 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 clever people have spent a lot of time elaborating over hundreds of years. But 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 (programming 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.
> 
> 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.
> 
> 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 mismatch 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 sums up my previous experiences with FP.

This is not to say that I won't give Haskell another try later on. After all, I all but have it as my goal to give every reasonably popular programming language a try at least once in my life. But for now, I'm afraid I need something 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)
> 
> 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 just saw an example of it in my OCaml classes recently.

Consider this :

"type Euro = float ;;
type Dollar = float ;;

let five_euros = 5. ;;
let five_dollars = 5. ;;
let silly_idea = five_euros + five_dollars"

And compare it to this :

"type Money =
| Euro of float
| Dollar of float ;;

let five_euros = Euro 5. ;;
let five_dollars = Dollar 5. ;;
let silly_idea = 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 turned from an error which could only be detected at run time to a static compile-time error.

This is the Ada philosophy in a nutshell : given precise enough type and function 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 programming languages have in common, although the precise implementation details 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.
> 
> 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 reference 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 of memory usage

Advantages of garbage collection:
- Due to economics of scale, garbage collection usually comes with a significantly reduced CPU overhead
- It is easier to deal with some tricky scenarii like cyclic references when 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, 
> 
> 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 :)


  reply	other threads:[~2015-11-18  9:44 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-15 20:42 Haskell, anyone? mockturtle
2015-11-15 20:51 ` Paul Rubin
2015-11-15 20:53 ` Nasser M. Abbasi
2015-11-15 21:50 ` Mark Carroll
2015-11-15 22:11 ` mockturtle
2015-11-15 22:48   ` Nasser M. Abbasi
2015-11-15 23:05     ` Mark Carroll
2015-11-16  4:11       ` Paul Rubin
2015-11-16  5:17         ` Nasser M. Abbasi
2015-11-16  5:48           ` Paul Rubin
2015-11-16  5:59             ` Nasser M. Abbasi
2015-11-16  6:47               ` Paul Rubin
2015-11-16  8:45           ` Simon Wright
2015-11-16 14:38             ` Brian Drummond
2015-11-15 23:19     ` Jeffrey R. Carter
2015-11-16  9:36       ` J-P. Rosen
2015-11-16 18:14         ` Jeffrey R. Carter
2015-11-16  3:59   ` Paul Rubin
2015-11-16  8:33   ` Dmitry A. Kazakov
2015-11-16  9:33     ` mockturtle
2015-11-16  9:45       ` Paul Rubin
2015-11-16 10:25 ` Hadrien Grasland
2015-11-16 11:19   ` Simon Wright
2015-11-16 11:25     ` Hadrien Grasland
2015-11-16 13:59   ` G.B.
2015-11-16 20:24   ` Jeffrey R. Carter
2015-11-16 23:23   ` Paul Rubin
2015-11-17  8:26     ` Dmitry A. Kazakov
2015-11-17  9:10       ` Mark Carroll
2015-11-17 20:09         ` Dmitry A. Kazakov
2015-11-17 10:49     ` Hadrien Grasland
2015-11-17 12:01       ` G.B.
2015-11-17 16:43         ` Hadrien Grasland
2015-11-17 18:04           ` Paul Rubin
2015-11-17 21:42             ` Hadrien Grasland
2015-11-18  4:36               ` Paul Rubin
2015-11-18  8:48                 ` Hadrien Grasland
2015-11-18  9:23                   ` Paul Rubin
2015-11-18 10:44                     ` Hadrien Grasland
2015-11-18 11:02                       ` Dmitry A. Kazakov
2015-11-18 12:41                         ` G.B.
2015-11-18 23:06                       ` Randy Brukardt
2015-11-19  8:56                         ` Hadrien Grasland
2015-11-19  9:19                           ` Hadrien Grasland
2015-11-19 21:27                           ` Randy Brukardt
2015-11-24 12:03                           ` Jacob Sparre Andersen
2015-11-19  7:22                       ` Paul Rubin
2015-11-19  9:39                         ` Hadrien Grasland
2015-11-17 13:01       ` Thomas Løcke
2015-11-17 16:45         ` Hadrien Grasland
2015-11-18  0:11       ` Paul Rubin
2015-11-18  9:44         ` Hadrien Grasland [this message]
2015-12-06 12:59   ` David Thompson
2015-12-07  7:25     ` Hadrien Grasland
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox