Catch up on stories from the past week (and beyond) at the Slashdot story archive

 



Forgot your password?
typodupeerror
×
Programming IT Technology

Why Lazy Functional Programming Languages Rule 439

Da Massive writes "Techworld has an in-depth chat with Simon Peyton-Jones about the development of Haskell and his philosophy of do one thing, and do it well. Peyton-Jones describes his interest in lazy functional programming languages, and chats about their increasing relevance in a world with rapidly increasing multi-core CPUs and clusters. 'I think Haskell is increasingly well placed for this multi-core stuff, as I think people are increasingly going to look to languages like Haskell and say 'oh, that's where we can get some good ideas at least', whether or not it's the actual language or concrete syntax that they adopt.'"
This discussion has been archived. No new comments can be posted.

Why Lazy Functional Programming Languages Rule

Comments Filter:
  • Mmmm, Kay. (Score:4, Informative)

    by jellomizer ( 103300 ) on Friday September 19, 2008 @11:23AM (#25071731)

    Hascal, and other functional languages may be good for multi-core development. However not to many programmers program in them... Plus I find they do not scale well for larger application. Its good for true computing problem solving. But today most developopment is for larger application which doesn't necessarly solve problems per-say but create a tool that people can use.

  • by Bob-taro ( 996889 ) on Friday September 19, 2008 @11:41AM (#25072019)

    The picture in the linked article is missing a beard.

    I was going to mod you funny, then I thought maybe a lot of people wouldn't get the beard reference [microsoft.co.il], so I decided to post instead. Anyone else want to mod parent funny?

  • Re:Why "lazy"? (Score:5, Informative)

    by tuffy ( 10202 ) on Friday September 19, 2008 @11:52AM (#25072209) Homepage Journal

    They're "lazy" because they don't do any work until necessary. For example, a function can return an infinitely long list, but only the elements you request will actually be calculated. Or, to compare them to Python, it's like having everything function like an iterator.

  • There's a more in-depth article on Javascript's functional capabilities here:

    http://www.hunlock.com/blogs/Functional_Javascript [hunlock.com]

    Other stuff I pulled out of Google for your perusing:

    http://dankogai.typepad.com/blog/2006/03/lambda_calculus.html [typepad.com]
    http://math.ucr.edu/~mike/lc2js.html [ucr.edu]
    http://www.joelonsoftware.com/items/2006/08/01.html [joelonsoftware.com]
    http://www.ibm.com/developerworks/java/library/wa-javascript.html [ibm.com]

    What this all means is that Javascript is the most widely deployed functional language in existence! And that's a fact you can take to the bank.

  • Re:Mmmm, Kay. (Score:5, Informative)

    by beelsebob ( 529313 ) on Friday September 19, 2008 @12:18PM (#25072625)

    Absolutely, and this is why there's one of freenode's biggest IRC channels, a pair of mailing lists with thousands of subscribers, and the Hackage [haskell.org] library/tool repository just waiting to help you solve your real world problem. Be it Compiler building [haskell.org], version control [darcs.net], writing interpretters for popular imperrative languages [perlfoundation.org], Writing 3D shooters [haskell.org], or a whole host of other tasks.

  • What would you describe as "Functional" then? i.e. What is the key difference between a Functional language and a language that has "Functional Aspects"? Show me the difference you believe is there and I'll show you the Javascript goods.

    Oh, and BTW? Academia agrees with me that Javascript is a functional language.

    Javascript is a functional language [...] The world's most-widely deployed functional language [nott.ac.uk]
    --Professor of Theoretical Computer Science Philip Wadler, University of Edinburgh

  • Re:Mmmm, Kay. (Score:4, Informative)

    by Dragonslicer ( 991472 ) on Friday September 19, 2008 @12:58PM (#25073213)

    On my computer, there's an infinite stream of ethernet frames arriving, an infinite stream of video frames leaving, an infinite stream of keyboard events arriving, etc.

    You keep on using that word. I do not think it means what you think it means.

  • Re:Mmmm, Kay. (Score:1, Informative)

    by Anonymous Coward on Friday September 19, 2008 @01:57PM (#25074307)

    That is true of almost any language. The point is that there's nothing those languages can do that can't be done, often more easily, with the current crop of popular languages. Elegance cannot beat convenience in the workplace, or in most at any rate.

    Haskell is extremely easy to read if you have any familiarity with modern mathematical notation. List comprehensions are set-builder notation, computerized. Guards are used analogously to "the big brace" in function definition notation. There are too many examples to list. This doesn't make it just elegant, but amazingly useful.

    Mathematical reasoning about your programs isn't constrained by the disanalogies introduced by the object system or "convenient" quirks. (I'm not saying syntactic sugar is bad, mind you. It just has the potential to introduce complexity). This is why Haskell is seeing use in high security applications, written by the sorts of companies with DOD grants.

    Functional languages in general will see more use as parallelization of code becomes more important. Potential parallelization is nearly automatic through the use of a few simple techniques (though tail-recursion kills). The relatively stateless nature can allow functions to automatically work in parallel, since their effects cannot influence other computations. They are somwhat similar to processes, as opposed to threads. They do not share state unless explicitly directed (IPC, in this analogy), whereas object/threading models potentially can.

    It's also kind of fun to work with Haskell.

    But realistically, designing an object system drawing on the strengths of functional programming is not difficult, and has been done, to varying degrees, many times. JavaScript is a fine example. Ruby and many other scripting languages implement functional programming constructs as method calls (perhaps with special syntax -- Ruby's .each is followed by a block, for example) Erlang's functions are literally services in a pool of services (the neat thing about that is that you can add new function instances to the pool at run time, as needed. Instant cloud computing, 10 years ago)

    I don't much care what I work with as long as it is functional enough.

  • Re:Mmmm, Kay. (Score:3, Informative)

    by snoyberg ( 787126 ) <snoyberg@users.s ... t minus caffeine> on Friday September 19, 2008 @03:13PM (#25075783) Homepage

    Well, in this case the "infinite stream" is really a stream of indefinite size. However, you can treat it as being infinite.

  • Haskell rocks. (Score:1, Informative)

    by Anonymous Coward on Friday September 19, 2008 @03:18PM (#25075877)

    Ill tell you from experience that while Haskell may be difficult to pick up and program efficiently in, if your program is going to be multi-threaded and ran on multiple processors it will be much safer, easier to debug, and less likely to run across nasty race conditions. With the push for these types of applications the move to functional languages is not very surprising, and although there is a slight performance loss to a language like C++ the ability to run reliably on multiple cores or an distributed array of servers kinda makes up for it.

  • by Tetsujin ( 103070 ) on Friday September 19, 2008 @03:28PM (#25076065) Homepage Journal

    Actually, when you're able to do it naturally in your language, it becomes a very useful thing to do. For example, when you want fresh variables in a compiler

    How is that better than doing (or basically the same in Java/C/perl/ruby/etc.):

    __compiler_var_num = 0
    def next_fresh_variable():
      global __compiler_var_num
      __compiler_var_num += 1
      return "_id_%d" % __compiler_var_num

    I hate to say "you're missing the point" because I feel that's unreasonably dismissive - though I kind of feel you are...

    IMO the point isn't necessarily that one method is "better" than another - it's that this idea represents an important and useful way of approaching programming problems. If you understand the style you can appropriate it - it becomes a useful concept for expressing problems and their solutions.

    So for instance - while you may not use recursion in C for general problem solving (due to the lack of tail-recursion optimizations which turn the thing into a loop) - understanding the recursive expression of a problem is useful for structuring your solutions, understanding what assertions must be made with respect to the state of the data at what points in the code, etc. - even if you structure your solution as a loop rather than a recursion.

    And it should be noted that you can implement infinite sequences in C++, etc. - generally the way to do this is with iterators, and the use case would be for feeding those iterators to algorithms that expect iterators... What Haskell brings to the table is that it encourages you to think of problems and solutions in those terms - learn the method and what you can do with it, how it affects the expression of your code - if you find it a useful idea it's easy enough to implement in most object-oriented languages...

  • Transactional Memory (Score:3, Informative)

    by wirelessbuzzers ( 552513 ) on Friday September 19, 2008 @05:28PM (#25078341)

    Thoughts on Haskell, from a Haskell programmer.

    Haskell has a very nice software transactional memory [haskell.org] library, which makes a lot of otherwise-difficult concurrency problems much easier. It's statically safe, too, unlike similar libraries for imperative/OO languages.

    Certain other language features are very nice. Monads are also extremely powerful once you wrap your head around them, and the type-class system and standard libraries make a lot of math programming problems much easier.

    The language also has downsides. The laziness makes it possible to build up an arbitrarily long chain of suspended computations, which amounts to a hidden memory leak. Laziness also complicates the semantics for "unchecked" exceptions, most notably division by zero. The combination of laziness and purity can make the language very difficult to debug and optimize. While the compiler has very powerful optimization capabilities, sometimes code needs to be just so to use them (like flagging things "const" or "restrict" in C), and this can make it hard to write clean code that runs fast.

    The other problem is that most programs need some amount of imperative code somewhere to do the I/O. This code has a tendency to be verbose, nasty and slow in Haskell.

    There are also some problems that would be relatively easy to solve in a very nice way within the semantics of the language (give or take), but are not solved well in the standard libraries. These include exception handling, global mutable state, strings and regular expressions, certain I/O operations, arrays and references. It would be very nice if the ST and IO monads were unified, and if references and arrays had nice syntax; this would reduce the ugliness needed to write those occasional bits of imperative code.

  • Re:Mmmm, Kay. (Score:3, Informative)

    by arevos ( 659374 ) on Friday September 19, 2008 @06:57PM (#25079673) Homepage

    Except nobody can read that. The line noise up there with perl!

    Nonsense. You need to be familiar with Haskell's syntax, but once you are, it's as clear as it can be for what it does.

    Reading the Haskell in evaluation order:

    filter (/= [])

    Filters out blank lists.

    groupBy ((==) `on` head)

    Groups rows whose first column is identical.

    toBranch = Node . (head . head) <*> (listToForest . map tail)

    This uses a function from Control.Applicative, but once you know that:

    (f . g <*> h) x = f (g x) (h x)

    It's not so scary. It takes the first cell from the first column of the group (head . head) to use as the value of the branch node, and then passes all the remaining columns (map tail) back into the listToForest function, and uses this as the subtree.

    Not trivial, but pretty clear when you think about it.

  • Re:Mmmm, Kay. (Score:3, Informative)

    by Pseudonym ( 62607 ) on Friday September 19, 2008 @10:51PM (#25081787)
    There are several correct meanings of the word "infite". The one being used here is "unbounded".
  • Re:Mmmm, Kay. (Score:3, Informative)

    by tkinnun0 ( 756022 ) on Saturday September 20, 2008 @11:36AM (#25085191)
    Java version might look something like this:

    import java.util.*;

    class Node {
      Map<String, Node> map = new HashMap<String, Node>();

      static Node asNodes(List<List<String>> input) {
        Node nodes = new Node();
        for(List<String> row : input) {
          Node node = nodes;
          for(String column : row) {
            if(node.map.containsKey(column) == false) {
              node.map.put(column, new Node());
            }
            node = node.map.get(column);
          }
        }
        return nodes;
      }
    }

Real Programmers don't eat quiche. They eat Twinkies and Szechwan food.

Working...