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 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!mx02.eternal-september.org!.POSTED!not-for-mail From: Paul Rubin Newsgroups: comp.lang.ada Subject: Re: Haskell, anyone? Date: Tue, 17 Nov 2015 16:11:31 -0800 Organization: A noiseless patient Spider Message-ID: <871tbocgjw.fsf@nightsong.com> References: <14533506-4289-4148-b8c4-e970f5778b26@googlegroups.com> <87si45msuz.fsf@nightsong.com> <35d6dc4f-4f2e-4e75-925c-e4acc7c8f112@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: mx02.eternal-september.org; posting-host="ac130717aa033f117b1251f50cb4c61b"; logging-data="3423"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19OtawSrbbi67+QQyo8XicF" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) Cancel-Lock: sha1:e2DeQ3qL0z7nZ7Brb8vSMj4yE2I= sha1:4cXJDPfxhgTHehVgY1fCEx812w4= Xref: news.eternal-september.org comp.lang.ada:28432 Date: 2015-11-17T16:11:31-08:00 List-Id: Hadrien Grasland writes: > 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 > 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. > 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. > 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. > when your mechanism to hide side-effects is conceptually so > complicated that a many learning resources feel a desperate need to > hide it under a rug 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. > OCaml... has a somewhat more pragmatic approach, encouraging the use > of functional constructs when they work, but leaving imperative > features around for those situations where they are the most > appropriate answer to the problem at hand. This is basically true from what I can tell. > 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. > Structure and Interpretation of Computer Programs was considered one > of the hardest programming classes ever taught at the MIT. The SICP course covered a lot of material in a short time, but FP wasn't that big or difficult an aspect of it. The textbook is really great and and it's online and you should read it if you haven't (mitpress.mit.edu/sicp). >> For immutable arrays, you'd use toList and fromList > Converting to and from lists sounds awful from the point of view of > performance, which is often the core point of using arrays. The point of arrays is constant-time random access. Without that you can use quadratic time to touch all the elements depending on order. The toList and fromList there just each make a single sequential scan so it's linear time just like the averaging calculation. Of course if you do it often enough, the constant factor can become a problem, and that's when to think about other approaches. > There is also pattern matching in OCaml, but in this situation, I did > not feel like its conceptual complexity was worth the code savings. Pattern matching is very basic to Haskell and Ocaml, so use it freely. > good old map, which will save us from the horrors of recursion this > time around. Haskell tends (more than Ocaml does) to use higher order functions like map or fold instead of recursion. That's partly because lazy evaluation (one of Haskell's more controversial features) lets you map over a huge list without creating an intermediate list, if the thing consuming the map output doesn't keep it around. > In functional programs, especially when lazy evaluation is used, I am > not convinced yet that the debugging methodology can always be so > straightforward, though I might not have met the right tool yet. It does take some getting used to. GHCi has an interactive debugger now, if that helps. > let a = 42 in > ...let b = 42 * a in > ......let c = 24 * b in Haskell lets you put the bindings at the same indent level or in braces, but it's a superficial difference. > 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. > 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 ;-). > I got the impression that Haskell type classes were pretty similar to > the interface concept in object-oriented programming : stating that a > type must have some methods defined in order to be used in some > context. Yes, something like that, but also restricting what types are allowed in some polymorphic terms. > From what I understood, what the C++ people are trying to do with > concepts is quite a bit stronger: they want to build a language > infrastructure which allows one to assert any static predicate about a > type before allowing it to be passed as a parameter to a > template. I think that's called "Axioms" which weren't part of the C++11 concepts proposal iirc. But I didn't follow the matter closely. > I find the idea quite interesting, but I'm curious about what the > implementation would look like. http://www.generic-programming.org/software/ConceptGCC/ > the only very large and successful functional program which I know of > is Emacs, and its Lisp internals most certainly do not exhibit the > latest and greatest that functional programming languages can do. Lisp is untyped so of course you won't see type annotations ;-). Emacs Lisp is quite old fashioned, descended from Maclisp which was written in the 1970s, before FP was a thing. Xmonad (xmonad.org) as someone mentioned is a good example of fairly advanced Haskell. >> I've generally found it easier to code stuff in Haskell than in >> low-level imperative languages, ... The main cost is that the Haskell >> code runs slower and uses more memory > How is this different from e.g. Python ? Python has a more ad hoc feel than Haskell. Its types are nowhere near as precise as Haskell types, and they are checked only at runtime. It uses stateful generators instead of lazy evaluation for making lazy sequences (that can lead to various annoying bugs), etc. But yes, Python is great for throwing quick scripts together, and I use it a lot. >> averages = [x+y+z | x:y:z:_ <- tails a] > Would it be correct of me to assume that if I asked you to handle end > points by reusing edge input values, your idiomatic Haskell answer > would be to append duplicates of the first and last input value on > each end of the input list ? Probably would paste the extra values onto the output rather than the input. Actually I'm not sure the zipWith2 example was so idiomatic at this point. I'm liking the listcomp version better too. > 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.