Haskell and creative freedom

As mentioned in a post last week, my experience with functional programming is pretty much all Scheme. I've gone through the SICP lectures and I get it... I am wary of !, and I understand why avoiding assignement is a good idea. After starting The Haskell School of Expression, I am curious as to people's visceral reaction to Haskell being a purely functional language. Do you find Haskell's approach creatively cumbersome at times? The feel I get from Haskell is that everything you program requires something "clever" in order to express it in a functional manner. Is that just my perception, is it a popular misnomer, or is it (even somewhat) true? I tend to sympathize with the kind of elitism that favors ideas that are "pure"... but can purity be an achiles heel? Why should I choose a language that denies me the understandibly dangerous power that accompanies assignment? What's "in it for me"? Is Haskell's type inference dependent upon assumptions about purity? Enlighten me, oh LtU gurus.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

IMHO...

... the benefit of Haskell's purity is twofold: first, it means that you get to use lazy evaluation consistently. Of course, opinions vary on the desirability of that. The other obvious benefit is that there's just one concept of striking generality that you need to master, namely monads, and once you have, you get to reap the benefits of referential transparency consistently across the board, even when doing I/O, manipulating state, dealing with concurrency, etc. This is pretty attractive, but definitely has a higher initial learning curve than the impure functional languages.

With respect to type inference, I don't think there are any particular challenges to type inference in a pure language vs. an impure one. On the contrary, type inference in a language with assignment is a bit more complex than in one without. On the other hand, if you're talking specifically about GHC, with its wide range of extensions to Haskell 98, no doubt some of those introduce rather interesting type inferencing wrinkles.

Haskell is... different

I picked up Standard ML pretty quickly (my first semi-pure FP language). For someone coming from imperative programming, it didn't look too weird.

Haskell seems to require a greater leap. I like the conciseness of the syntax, but that conciseness can leave a newbie perplexed.

So far, learning Haskell has been a little like programming Perl: Enough syntax that if you don't constantly use the language, you may feel lost days later. And, just when I think I am ready to read some serious code, I'll stumble across some construct that will throw me for a loop. This is less due to the purity of Haskell than its syntax.

For a nice (toy) example of how different Haskell can be, see http://www.willamette.edu/~fruehr/haskell/evolution.html

Actually, it's liberating...

...the reason is that I can (almost) reason the way I want to about my programs, and the reasoning is correct. The reason is that I can factor my programs into functions as small as I like, and the type system catches any errors I make composing them again.

It feels really good to work in a language that, as a tool, actively supports your work. I think Scheme or Smalltalk don't hinder you, and C (and to a lesser extent Java) actively harm your efforts. Now, you can do better than Haskell, but there's no doubting the fact that it's just enormously fun to program in.

How are you using Scheme?

More specifically, how often do you use the various "bang" forms/procedures in it, like set!, set-cdr!, and such? How often do you explicitly write loops (e.g. with the do special form or with named let)? How comfortable are you with the SRFI-1 fold procedure?

The thing I'm getting at is whether your difficulty is just with Haskell in particular, or whether it's with purely-functional programming in general. Can you write Scheme in a purely functional style?

I personally use bang operators in Scheme very, very sparingly, and use map and fold considerably more often than explicit looping constructs.

Of course, Haskell poses difficulties above this-- in particular, I find it very, very hard to get my head around monads.

The only time I'll use a bang

The only time I'll use a bang operator is in implementing something cute like procedures with shared state... so I guess pretty rarely. I guess maybe that answers my question about needing impurity, since I don't really use it anyway. I feel like I know how to program functionally. But one prospect I find attractive is the idea of using stored continuations for web programming, which requires assignment. I guess I also just wanted to understand the reasons behind throwing something away that could potentially be of use, which this thread is helping me with.

We talk more about the clever stuff

You can do a lot in Haskell without needing "clever" stuff, but I can see why you might get that impression. Hard-core Haskell hackers amuse themselves by implementing the idioms of other languages in Haskell (see, for example, OOHaskell), and this often involves some pretty convoluted code, but that sort of thing isn't typical.

As for why you should choose a language that denies you assignment: Haskell doesn't deny you assignment. It just forces you to be explicit about when you're using it.

Haskell and creative freedom

Do you find Haskell's approach creatively cumbersome at times?

Not at all. Or at least, not at all now. I learned Haskell about a year ago and I was often flummoxed at first at how to approach problems. As I've learned more and gotten more experience, purely functional approaches make more and more sense.

Why give up "the understandibly dangerous power that accompanies assignment"? Because you never have to ask again "How did it get that value?" during debugging. Because you never have to worry about whether the variable is holding the new value or the old value.

At work I program in C++. But I'm finding purely functional approaches now often come to mind first. And I have to control the urge to make everything const to keep those damn variables from changing under me.

My experience is that translating imperative code into Haskell gives you code that seems to depend on clever tricks. Since most of us learn the basic algorithms in imperative languages, our early Haskell code tends to have a heavy "accent." As I've gotten more fluent in the new language and been exposed to fluent Haskell from those who've gone before me, my Haskell is getting closer to a native tongue.

There are some articles (I'm too lazy to look them up tonight) on functional graph algorithms. I found in them great examples of how to think functionally. The functional algorithms are completely different from their imperative equivalents, but neither is cleverer or trickier than the other--they're just different.

I'd encourage you to stick with it and to find great Haskell to read. (Sadly, not all Haskell code out there is great, or even especially functional.) Your perceptions may change with more experience.

Great Haskell code to read

I personally would very much appreciate pointers to great Haskell code to read - beyond the Prelude. Any suggestions?

Try these

This page at haskell.org lists several applications written in haskell, if you're interested in real-world examples. Darcs and Pugs seem to have a good amount of buzz around them, in particular.

You're correct.

Functional programming sacrifices "expressivity" at the cost of gaining program correctness.

If correctness doesn't matter to you, then the pain is basically not worth it.

(P.S. Personally, I think correctness should matter a great deal if you care about what you're doing. Big businesses should have jumped on functional programming instead of the pointlessness of Java.)

On further reflection.

The problem with FP languages is probably the fact that there is no (as of yet) objective and quantifiable way of measuring program correctness.

I understand that showing correctness in the strict mathematical way is an impossible lost cause; however, there is also the "soft" meaning of correctness, i.e. meaning "fewer surprises and less bugs"

In the end, the "object-oriented" snake-oil peddlers won out, and I find this sad.

Personally I program in Haske

Personally I program in Haskell because it offers me a /gain/ in expressivity. Imperative languages just can't manage the kind of semantic lego that monads and monad transformers offer.

We talked about this at length already.

"Expressivity" is an emotionally-charged word much like "ease-of-use" or "cleanliness".

In the few cases where you can define "expressivity" in a scientific or objective manner, it boils down to "there's more than one way to do it" of the Perl infamy, and I'm sure that that isn't what functional programming is all about.

In short: we achieve "functionalness" by taking away features, (mainly, by taking away stateful/destructive operations) not by adding new features.

Corollary: higher-order functions, etc. do not a functional language make.

It just does not justify

In the few cases where you can define "expressivity" in a scientific or objective manner, it boils down to "there's more than one way to do it" of the Perl infamy, and I'm sure that that isn't what functional programming is all about.

It just isn't true.

Expressivity can be defined pretty precisely, for example - number of program tokens used to solve a problem.

Almost any language gives you "more than one way to do it," but quite a small number of them allow you to do it short.

In short: we achieve "functionalness" by taking away features, (mainly, by taking away stateful/destructive operations) not by adding new features.

If you look at history of PL long enough, you will see that first PL was lambda-calculus. And then Turing introduced his famous machine which conquer the world. So, you achieve nonfunctionalness (pardon my frnch) by adding stateful/destructive operations.

higher-order functions, etc. do not a functional language make.

Okay, but vice versa. And in functional setting they are useful while in other setting theay are often useless.

Hm.

Perl goes a long way towards shortening the number of program tokens.

And in any case, I don't think anybody argues that Perl isn't expressive.

Whether or not this sort of "expressiveness" is useful or relevant is a whole different discussion, though.

P.S. Higher order functions with stateful/destructive operations -- also sometimes known as "spaghetti code". :)

i can attest...

... it's both useful and relevant.

In any case...

...I think CS should focus firstly on a) safety and correctness and b) time/space complexity.

Anything else can wait until these two problems are solved first, in my opinion.

well...

while you wait, useful and relevant expressive contructs can help you achieve high productivity in an unsafe and incorrect environment... :)

Higher order functions useless outside of FP?

I strongly disagree...but read the disclaimer in the next paragraph first before disagreeing with my disagreement.

Of course, that depends on the definition of FP; if the definition of FP depends solely on the existence of higher-order functions--then your statement becomes a tautology. In which case I no longer disagree-- however tautologies aren't very interesting. :)

If what you mean is "HOFs are often useless in languages/environments where mutable state exists", to THAT I strongly disagree. HOFs are highly useful (and widely used) in languages like CL, Javascript, and Smalltalk (I'm including Smalltalk blocks as HOFs due to their being lexically scoped)--all of which have a strong imperative tradition.

And in the OO world, objects subsume many uses of HOFs--an object is, after all, a HOF with multiple entry points and the environment explicitly declared. That said, HOFs are syntactically more convenient in many places, which is why Java added inner classes (ugh), and operator() is such a useful thing in C++. Even lowly C can make effective use of function pointers to greenspun up HOFs, though the result is frequently a mess. :)

At any rate, HOFs are quite useful in languages with destructive update. Now, if you add pervasive laziness (a la Haskell) to the mix, that's another kettle of fish; but mixing pervasive laziness with destructive update is asking for trouble, even without HOFs around.

If you mean something else altogether, and I've completely misunderstood you... then I withhold agreement (or disagreement) until such understanding is reached.

You say: "In the few cases wh

You say: "In the few cases where you can define "expressivity" in a scientific or objective manner, it boils down to "there's more than one way to do it" of the Perl infamy, and I'm sure that that isn't what functional programming is all about."

Don't be so sure about that, it's sure got a lot to do with why I use functional programming. The absence of side-effects allows things that perl can't do, whereas I can always regain the effects via monads if I want them. The clear lack of side-effects outside monads is a feature in and of itself.

In any case.

You can use these same "expressive" features in imperative languages, too -- the problem being that this particular coding technique is more commonly called "spaghetti code" or "big ball of mud".

On the other hand, it is true that FP is restricted enough to make "expressive" features safe for general use.

You can't use the "this code

You can't use the "this code can be proven to have no side-effects via the type system" feature in imperative languages, or the "this code only has this set of side-effects that cease to be visible beyond that scope" feature. I find these to be important things to express about my code.

OK, point taken. :)

I see what you mean.

sorry

but expressive languages have no bearing whatsoever to spaghetti code.

expressive means concise, clear code. saying a lot with few words...

Uhm.

By that token, "GOTO" is the most expressive control structure there is.
Just a small but representative example.

no

saying goto 176876 isn't saying a lot. in fact, it says nothing other than to shift control flow to a specific memory location...

it isn't expressive by any means.

Why not?

It expresses tail recursion, continuations and all of the "structural programming" primitives in one clean and simple instruction.

In other languages you need 5-10 complicated "core primitives" with crufty syntax to do what one "goto" does. (Compare to C's "longjmp".)

I guess what I want to say is that "expressiveness" is orthogonal to "safety"; indeed, oftentimes the blind drive towards "expressiveness" leads to profoundly stupid and unsafe decisions.

Look for the paper by Matthia

Look for the paper by Matthias Felleisen on comparing expressiveness. (Previously mentioned on LTU and this discussion) for a rigorous formulation as what expressiveness means . Goto does not add any interesting expressiveness to a language. All the interesting cases are covered with the standard control flow constructs. I'd argue Continuations are in fact MORE expresssive than goto's because the runtime system deals with the environment structure for you. Please go spend several months reading some PL papers and reading books such as Benjamin's TAPL before you contribute to LTU again. Please.

Lets keep it civil, please

This is not /.

Comments like "Please go spend several months reading some PL papers and reading books such as Benjamin's TAPL before you contribute to LTU again" do not add anything of value to the discussion. Even when accompanied by "Please". :)

Oh boy...

I guess I have to step in...

Please keep LtU civil, but please do ignore posters if you think they are simply trolling. LtU was, and will remain, open to people interested in programming languages at all levels. We will, however, not let ourselves be taken advantage of because of this.

If you think a question or remark is sincere - by all means, answer it (preferably by linking to previous LtU discussions, of course).

oh boy

you really stand by your arguments, huh? as unreasonable as they may be...

Using tail-recursion isn't the same as saying "goto :foo". They may be implemented behind the scenes as computed gotos, but the user-level syntax and semantic is very different; and the constructs are a lot higher level than goto. In other words: using tail-recursion won't lead to incomprehensible spaghetti code as plain goto would. ( not so sure about continuations )...

i guess you're telling me java and its very inexpressive syntax is a lot more safe than, say, haskell? i don't think so...

Which is exactly my point.

"Expressiveness" != "high level", and certainly != "safe".

I would very much like to keep the three concepts separate.

it is not your point!

Quit twisting arguments to your favor!

Every very high level language brings together high level constructs which make them very expressive, in that you can say a lot with just a few expressions.

Low level means you have to carefully craft all the details by yourself, using only the limited raw low level constructs. It's not expressive by any means, let alone you implying "goto" is "expressive".

Java is not expressive because its not that high level as a language, just another mindlessly imperative C descendant. Yes, it features millions of very high level APIs to do any kind of job, and that is the only saving grace of the platform.

As to safeness, yeah, i'll keep it separate from expressiveness since they really have nothing to do with one another...

i think your point is to anger LtU readers with pointless args...

Hm.

Some DSLs are certainly as high-level you can get, while at the same time being very un-expressive.

Also, there are some low-level languages that are "expressive" in the sense that you can code some constructs with them that would be too complicated or even impossible in some of the more high-level languages.

I see what you mean, but the definitions are still very unclear and hand-wavey. Some sort of more formal definition would be nice.

One of the ways in which low-

One of the ways in which low-level languages are unexpressive is that they tend not to carry much static information.

Of course, there's a sense in which most programming languages are equivalent for expressiveness - modulo IO and the likes, they can all express the same range of dynamic behaviour.

Isn't expressive at all, BTW

Using already mentioned measure of number of tokens per problem solution, I think that GOTO is less expressive than, for example, tail recursion.

You need to say "GOTO a_tail" instead just "a_tail" in tail-recursive definition.

Please, present your metric of expressiveness if you disagree.

Lambda, the Ultimate blog name

Using already mentioned measure of number of tokens per problem solution, I think that GOTO is less expressive than, for example, tail recursion.

Quite so. Perhaps it's a good idea every now and then to revisit the papers which gave this site its name, which are particularly relevant in this case: the most obvious being Lambda, the Ultimate GOTO, with Lambda, the Ultimate Imperative a close second, and the other Lambda Papers are also relevant.

The point as it relates to this discussion being that lambda is a more expressive construct than GOTO, in most senses of the word "expressive", and certainly in the sense which rmalafaia used, "concise, clear code. saying a lot with few words". A broader point is that there certainly are objective things which we can say about expressiveness. On that subject, Felleisen's paper has been mentioned multiple times, but I think it's worth pointing out his summary in this ll-discuss post, as well as these slides, and for completeness, the formal description in the original paper.

"Few words"?

"Few words", as in, "LZW compression"?

(I know this isn't what you meant, I'm just playing devil's advocate.)

Again, "expressive" != "clear". Neither does "expressive" boil down to "concise", in that trivial sense that using short variable names doesn't make code more "expressive".

For some objective meaning of "expressive", "expressiveness" simply means "more and more varied language constructs". This is fine, but generally viewed as a broken way to design code. (This is also the philosophy that gave us Perl, by the way.)

Perhaps, again, you meant something else, in which case please give some sort of objective definition of "expressiveness".

(I think this conversation is getting tiring, by the way. :))

Uhm.

Going by your comment, "GOTO LABEL NAMED a_tail_label" is the least expressive solution, while simply calling "a" tail-recursively is the most expressive solution.

I think I misunderstood your point.

The bigger the number of toke

The bigger the number of tokens per problem solution, the less expressive the language is.

I even do not get your point readily, because measuring expressiveness as proportional to number of tokens is the most counter-intuitive idea I could ever think of.

Please rephrase.

The two sentences of your post are self-contradictory.

Nitpicking

Hmm. As I read it:

The first sentence is a definition. The second sentence is an opinion.

"Expressivity" is an emotiona

"Expressivity" is an emotionally-charged word much like "ease-of-use" or "cleanliness".

That's a fair point. It is subjective.

Having said that, I do find that if the problem that I'm solving is a high-level one, I can get the same (or better; more robust, certainly) code in Haskell quicker than any other general-purpose language. (This may mean that Haskell isn't general purpose; it's a DSL for high-level programming.)

They key here is that Haskell almost forces me to ignore details that I would have to concern myself with in other languages, forcing me to concentrate on the high-level tasks instead. An example is data structures: Haskell forces me to think about a data structure's conceputual structure and ignore how the bits will be physically laid out in memory and writing the zillions of accessor functions that a procedural OO language would require me to provide.

In other words, Haskell encourages me to think big thoughts, where in another language I would be more encouraged to think little thoughts.

This is a freedom of sorts. OTOH, it can also constricting if you want to or need to think little thoughts. Some (not many, but some) programs depend on scrounging cycles or keeping tight control on memory usage to be useful. I know this; I hack database servers for a living. I don't write those sorts of programs in Haskell, though I do occasionally prototype so I can get the "big thoughts" sorted out before concentrating on the little thoughts.

A few corrections:


They key here is that Haskell almost forces me to
ignore details that I would have to concern myself with in other languages, forcing me to concentrate on the
high-level tasks instead. An example is data
structures: Haskell forces me to think about a data structure's conceputual structure and ignore how the bits will be physically laid out in memory and writing the zillions of accessor functions that a procedural OO language would require me to provide.

Don't tar all OO languages with the particulars of C++ or Java. Other than C++, how an object is laid out in memory is an implementation detail--the layout of a particular object is typically not predictable from nor controllable by the class definition. Likewise with encapsulation--many OO languages dispense with compiler-enforced encapsulation; others make it easily circumvented with "property" declarations. Writing accessors and mutators is primarily a C++/Java pursuit.

Actually, one interesting dichotomy found in industry is between "prototype" code and "production" code--the former is developed with the expectation that it will be thrown away rather than deployed, (an expectation that is unfortunately violated often), the former is developed with the expectation that it will be deployed and subject to upgrades and other maintenance post-deployment. Many in the former camp strongly resist encapsulation--it gets in the way. Many in the latter camp embrace it--it's far easier to replace a member function than a data member.

At any rate, prototyping performance-critical code in a HLL before implementing the production version in a C/C++ isn't a bad idea. IF nothing else, it prevents your prototype from being deployed in production against your wishes. :)

Fair point

Don't tar all OO languages with the particulars of C++ or Java.

Yes, sorry, I didn't mean to do that. If I were OO programming and I wanted to "think big", there are languages I could do that in. (Sather or Eiffel would be my personal choice, probably because I haven't ever used Smalltalk.)

Though to be fair, even when programming in Erlang, I seem to spend time writing things that are like accessors.

Yeah, but...

I've seen these arguments before - most of them are valid. However, for something completely different:

Take a good book on algorithms (or applied combinatorics), say this one. Look at all the statefull, and clean, algorithms. Are we all convinced then that for every program in said book a good pure functional translation exists (with similar complexity/consiceness/easy correctness proofs)?

I am not. And I'll only be when someone gives me a copy where, say, 90% of all those algorithms are translated into simple efficient pure functional variants.

Second argument, even if all these algorithms are translated (maybe, it's not even that hard), then probably this is done by making lots of assumed state explicit. (Let's say, for the argument, that pure functional programming boils down to making every datastructure explicit.) What did we gain?

I've seen the "pure FP is so close to math therefor seriously cool" argument pop up from time to time. Well, as far as my limited math knowledge goes, not explicitly writing down what can be assumed to be implicit knowledge is one pretty damn hard mathematical technique to keep theorems/formulas/proofs readable. Wouldn't that apply also to programs?

(And as a side thought - refactoring programs where everything is made explicit? Duh, I can only imagine loads of programmers with major headaches!)


Btw, "Haskell School of Expressions", great site!

Hm.

Well, as far as my limited math knowledge goes, not explicitly writing down what can be assumed to be implicit knowledge is one pretty damn hard mathematical technique to keep theorems/formulas/proofs readable.

Well, this is also sometimes known as "sloppy math".

Anyways, there are good practical arguments for strictness.

Purely functional data structures.

Are we all convinced then that for every program in said book a good pure functional translation exists (with similar complexity/consiceness/easy correctness proofs)?

No, we are not. Okasakis book is a good start though.

Monads encode the implicit

Often the implicit knowledge can be encoded once-and-for-all - that's part of the attraction of monads and the like.

One of the possible gains is knowing that there are no side-effects other than those we desire - in turn that can make it possible to support individual effects that would be impractical in combination.

Oh wait! I might...

... actually also try to answer the questions of the orignal author.

Do you find Haskell's approach creatively cumbersome at times?

Never. It's refreshing.

The feel I get from Haskell is that everything you program requires something "clever" in order to express it in a functional manner. Is that just my perception, is it a popular misnomer, or is it (even somewhat) true?

It isn't true. If you learn the trick of translating imperative programs to functional programs it's easy to program Haskell ;-). May not be the nicest way though.

I tend to sympathize with the kind of elitism that favors ideas that are "pure"... but can purity be an achiles heel?

Depends on who you ask. I would say 'yes', referential transparancy is annoying, I see no reason why I need it.

Why should I choose a language that denies me the understandibly dangerous power that accompanies assignment?

Come again? What's wrong with an assignment ;-). Old debate, if you find that assignments are bad, well, choose Haskell. I like FP because I like combinatorial style programming (parser combinators, tree visiting combinators, document layout combinators, stuff like that). For that, you need a functional language. Personally, I find it has little to do with purity, monads, or laziness.

What's "in it for me"? Is Haskell's type inference dependent upon assumptions about purity?

I guess they can optimize parts of the program better since they know that these, or in Haskell's case, everything is without side-effect. Don't see why the type system would make assumptions on purity; that seems counter-intuitive. Anyone here who knows the answer to that question?

Enlighten me, oh LtU gurus.

You are standing in the middle of my ship.

Combinators.

You can do them perfectly fine in C++, for example.

I don't think there is any relevant link between combinators and "functionalness".

Proof it.

Give me typesafe definitions of S/K combinators in C and S/K combinators in ML/Haskell. Then we talk.

Why S/K?

I think I lost the thread of discussion here.
What do S/K combinators have to do with typesafety or even programming for that matter?

In any case, templates and operator overloading can implement higher-order functions in C++ quite cleanly. (Closures are tricker, though.)

Trickier...

... but still a solved problem.

Reasoning at the level of text

What I prefer about haskell is that I don't have to keep an execution model in mind while programming. That is, when I try to figure out how to write a piece of functionality, or when I try to decipher a bit of code, I only have to think in terms of shuffling around textual tokens, as opposed to having to mentally simulate running the program. Referential transparency is a very important part of this.

With regard to the cleverness required to program in haskell, I think you may be underestimating how often you fall back on idioms that you've come to take for granted in your language of choice. For example, the OO community has so many different kinds of "cleverness" that they even have a word for them: design patterns.

If transition to Haskell is difficult, how about a functional C?

As I have similar problems with some posters in my effort to learn Haskell as described in these threads, I was wondering if a functional language with C-like syntax could be an evolutionary step to help programmers approach functional programming. I don't think it would not be too bad, after all. Some examples:

//the classic factorial function for integers
int factorial(int n) {
    if (n > 1)
        return n * factorial(n - 1);
    else
        return 1;
}

//a generic version of factorial using C++ template-like syntax
template  T factorial(T n) {
    if (n > 1)
        return n * factorial(n - 1);
    else
        return 1;
}

//another possible generic version combined with
//pattern matching, using 'auto' for generic type
//(as in C++ next standard)
auto factorial(auto n) {
    if (n > 1)
        return n * factorial(n - 1);
    else
        return 1;
}
auto factorial(0) {
    return 1;
}

//the quicksort algorithm; type inference works as in FP
auto sort(auto l) {
    auto f = first(l);
    auto r = rest(l);
    auto l = less(f, r);
    auto g = greater(f, r);
    return sort(l) + f + sort(g);
}

//recursive generic types with C-like syntax
type tree(T) {
    tree(T) | nil left;
    tree(T) | nil right;
}

//enumerations
type Direction {
    Left | Up | Right | Down;
}

What do LtU members think? I know the programmer has to type more characters than Haskell, and those ugly semicolons are still there, but I think it would be easier on the eye for someone coming from C to grasp the above rather than the same code in Haskell.

It's desperately need.

In my opinion, the business world desperately needs something like this. IT infrastructure is going to implode under its own weight unless something is done to curb complexity and encourage "smart" code.

Corollary: There's a real business case hiding somewhere here; one could make lots of money if this is marketed correctly. :)

I am willing to do a C to functional C translator...

...as long as LtU members help me out with which functional features to include in the language or not. I totally agree with your thought that the IT infrastructure is going to implode under its own weight.

I would vote for the following functional features:

  • functions as first class entities (of course!)
  • closures (it goes hand-in-hand with the above)
  • algebraic types

I wouldn't choose the following features, for the following reasons:

  • tail recursion optimization; I don't know how to do it in C; maybe using setjmp/longjmp?
  • pattern matching; it does not seem very important to me, at this stage. Without pattern matching, it means that the programmer has to use if-then-else more
  • currying; as long as functions are first class values, currying is not that important: it can be 'simulated' with lambda expressions.
  • lazy evaluation. It's difficult to grasp, and lazy infinite lists can be simulated by functions that calculate those lists.

Please take the above lightly; I am not trying to start a flamewar. All I want to do is to have FP get wider acceptance.

I would also like to have threads and channels as first class entities, as well as direct interfacing with C. The language will have garbage collection (that's easy to do, I've done it quite a few times, both mark & sweep and copying algorithms).

The translator could be done in a few weeks, with the help of tools like the Gold Parser Builder. The translator will output C code as an intermediate language using some form of GCC as the compiler.

If LtU members agree, I will first write the grammar and then present it here so as that we can discuss it.

Also,

  • Pre/post conditions would be nice.
  • Strict type inference so people can't play with types manually.
  • Destructive updates should be clearly marked somehow.
  • Union types.
  • Nested scopes!
  • For extra fun, interned atomic strings a la Prolog/Lisp would be useful.

In addition, once you've implemented some sort of public/private visibility for variables in a scope, you basically have a more modern and safer version of C++.

Then, once STL is re-implemented with type-inference, you might have something truly viable on your hands.

Pre/post conditions would be

Pre/post conditions would be nice

checked at run-time or compile-time?

Strict type inference so people can't play with types manually

yeap, I agree on that.

Destructive updates should be clearly marked somehow

I think it's better not to have assignments at all. After all, the principle of no destructive updates is one of the most important principles of FP, because it forces people to avoid loops and think about recursion.

Union types

Yeap, I agree on that too, supposing you mean union as in ML and not as in C.

Nested scopes!

Does that fall under closures?

For extra fun, interned atomic strings a la Prolog/Lisp would be useful.

I don't know what that is. Could you please elaborate?

once you've implemented some sort of public/private visibility

my idea is to introduce functional programming to the masses...therefore I would like to start with something simple, like C (which has only records and functions) and extend that to reach to a good functional programming status. So I was thinking of public/private access at unit level, much like 'static' in C.

Let me say here how important is to keep things as simple as possible.

Re:

Assertions... Both static and runtime are usually needed. (Though couldn't you do this automatically -- whatever can't be inferred statically gets turned into a runtime assertion?)

I don't know what that is. Could you please elaborate?

Atoms in Prolog or symbols in Lisp... Basically, the advantages of const char* in a safe manner. (This should solve part of the problem with strings and C.)

As to the "private/public" thing -- I was merely thinking out loud about the fact that it's the only thing that is missing w.r.t. "object-orientedness". (Provided you already have closures and type inference.)

With a minimal effort you could get OOP for free, as well.

You can do OOP if the languag

You can do OOP if the language supports public/private types. If a public type contains a member of private type, then you got what you want.

More Fun, Less Functional

It might be useful to hook low level programmers on a more advanced (but less functional) gateway language like Cyclone .

The syntax?

Why do you think its the syntax that is the problem with learning Haskell and functional programming?

It's not the problem, but for

It's not the problem, but for those who have used nothing but C-like languages it may well be a problem. I've known enough people get incredibly frustrated at Haskell's layout rule until someone finally pointed them at the Report section on it - that was the way I got the only clear explanation I saw, too.

Learning syntax and FP at the same time...

...is difficult for people that have years of experience in C/C++/Java-like languages.

Algebraic datatypes

I suspect that programming with algebraic types/pattern matching is too different from C to be glossed by mere syntax. Then again, I do not program in either C or Haskell.

C users do have switch statem

C users do have switch statements, so you can introduce it all as a new kind of union with a new kind of switch statement to go with it and that makes some sense.

This seems to be pretty much

This seems to be pretty much what Felix is aiming at.

i think...

...it's easier to learn a new syntax together with a new approach to problem solving ( FP ) than learning a new approach with the same syntax for which you've aquired lots of idioms and bad habits along the years.

perhaps this could ease the transition:
Haskell for C programmers tutorial

it was covered here in LtU before...

besides, i think C lousy syntax would not go along well with FP...

I tried it, but I was lost.

It's a totally different world...trying to keep up with the syntax and the semantics got me into confusion. And I know a little bit of ML...I can't imagine the horror of people that only know Java and Basic, for example.

Anyway, that's just me. Most probably there are other people that the approach you describe works better for them.

I'm not so sure.

When I was just learning about FP (through OCaml), I had some difficulty dealing with OCaml's syntax, and I thought something like this would be really nice. As I spent some time thinking about how I'd design such a language, the problem I began to encounter is that there are legitimate, syntactic advantages to an ML-like syntax, e.g. currying/no paren'd,comma'd functions arguments, let-expressions, everything's an expression, etc. While these issues could probably be resolved in a C-syntax FP (c.f., Nemerle), I'm not convinced that keeping the C-syntax is worth it. Maybe it is.

Yes, it can be cumbersome

Do you find Haskell's approach creatively cumbersome at times?

Truthfully, yes I do. It completely depends on what kind of program I'm writing. For things that are very transformational in nature, functional programming is a perfect fit. For other things, like simulations, it can be awkward. I can factor and simplify and quite often a certain beauty comes to light with a functional solution. But just as often there are times where I just wish I could destructively update things, because it's simpler. Try writing a video game in a purely functional style (just the simulation side; ignore I/O), for example. It's possible, and I've done it, but I'd be hard-pressed to say the result is simpler or cleaner than imperative code. This, IMO, is one of the reasons that languages like Python have large followings. When you write Python, you essentially get the core benefits of functional languages, but there's no religion, no pressure to be pure. I'm not talking about maps and lambda and so on, but simply manipulating lists and other data structures without having to micromanage variables and so on.

core benefits ... but no religion?

Perhaps no "FP purity" religion, but along with batteries, Python comes with its own religion included ;-)

I'm not sure what the "core benefits" of FP are exactly, but I think the things you said can be said for Perl, Tcl, Ruby, Lua, etc. And Python strikes me as a very much imperative language.

Sometimes I find the restrictions of FP "focusing". Limitations in expressiveness (e.g. no side effects) forces me to rethink how I typically solve a problem. Even if I don't adopt a functional approach, I have a better understanding of why I needed to take a more imperative approach. (And when I do I tend to pay much more attention to variables, side effects and modifiable state).

I'm not sure what the "core b

I'm not sure what the "core benefits" of FP are exactly, but I think the things you said can be said for Perl, Tcl, Ruby, Lua, etc. And Python strikes me as a very much imperative language.

If you go back to earlier days of functional languages (e.g., Hope, fp), I think the most impressive part of them--relative to common imperative languages of the time--was that you could sling data structures around without thinking about memory. You could easily create new data without managing pools, without preallocating variables to a fixed size. If you have a list of filenames and want a list of which of those filenames end with ".txt", then that's easy to do. You just make a new list with those filenames in it. That leads to a rudimentary functional style, one that you don't even think about as being functional.

I agree that this applies to Perl and the other languages you mentioned.

What I typically find is that a functional style is great for most things, but sometimes it's much simpler to have some data globally stored and modifiable. I think that's a common experience. Pure functional programming is still clearly a niche. (I know and enjoy Erlang--one of my favorite languages--but Erlang gains much of it's utility from decided impure concurrency capabilities that can serve much the same purpose as destructive updates.)

... impure concurrency capabilities...

While Haskell seeks to rope side effects, destructive updates and other FP impurities into a theory backed exception to purity, Erlang (and my favorite FP: Standard ML) doesn't bother.

A lot of my programming deals with modifiable state. I can compare a network server I wrote in Tcl (and then again in C++) with a rewrite (redesign, actually) in Standard ML and I find that my ML implementation makes very rare use of "ref" variables. This is a good thing.

If Haskell is able to capture much of what I tend to do within monads, then I suppose dealing with "expressiveness" and "creativity" is defined by how much I am willing to put up with the monadic syntax.

Then again, since I build networking servers for a living, I may find myself stuck in that syntax more than normal Haskell!

This begs the question (syntax and efficiency aside): What can you not do in (as impure as you need to be, but still legal) Haskell, that you can do in something like Python or Perl? (here I am just considering Haskell as a higher order language, not a pure functional one.)

Pretty much nothing. I don't

Pretty much nothing. I don't find monadic syntax too big a deal either - aside from the need to use return or let occasionally it's no different to any other language I've used that's dealing with sequencing in a clear manner, and getting to apply that in the context of something like parsing is rather nice.

Personally I don't mind if much of my code's monadic at first glance (in fact I tend to find pure transformations dotted throughout my monadic code, and their purity is useful).

Simulations and transformations

In my day job I write software to process financial data, which means that most of my code is what you call "transformational". The language we use is not unsurprisingly Java, and I'm very unhappy with this. I find that Java is a terrible language for this sort of thing. We're currently stuck with Java 1.4, so we don't have generics. The result is that I spend my days fighting with the Collections API. Having lately played around with OCaml my dissatisfaction has grown to record high level, and every day I look forward to going home to hack on my OCaml code.

It is no wonder Java is so bad a this. Object oriented programming has it's origins in simulation software, which is evident in the name of the first OO language; Simula. But for the sort of data handling that I typically have to perform every day it is a bad match. There's not much to simulate. (Unless you're writing software to simulate the market, or you're implementing financial models of course).

I mentioned that I've been using OCaml lately, and as you might know, OCaml supports OO in addition to FP. As I began using OCaml I was expecting that as a long time imperative OO programmer I would quickly resort to object oriented programming whenever I felt that FP was getting in my way. But as I started porting an old utility written using OO Python I saw that getting rid of everything OO made the code cleaner and simpler. And I found that the FP style of programming matched the task perfectly (simple transformation of textual data).

I cannot praise OCaml enough. After flirting with FP in Python, writing an Emacs extension in Elisp, and trying to break into Lisp/Scheme, I feel that I *get* FP for the first time. For me there's something very natural about OCaml, it did give me some initial resistance, but only for the first couple of days. I suppose this applies to ML in general since I haven't touched the OO part of OCaml yet.

But my main thesis is that for a vast array of todays "enterprise" software challenges, FP is in fact vastly superior to OO. The major problem with FP is the lack of existing software. If you're going to tell your boss that it's time to replace all that Java crap with something more suitable, you have to be prepared to show how every part of the system can in fact be replaced. When the majority of the software is built around the large collection of Java frameworks and libraries out there, you'll have a hard time explaining them just how making the switch is going to increase production. Management like to have options, and I don't blame them. If you rely on a piece of software it is reassuring that you can have it replaced if the company that backs it goes bust, or the code simply starts to suck.

I know that much of this is just a rehash of what many others have written here at LtU many times before. It is just my lenghty way of saying "Me too!", and "OCaml rocks!", and I needed to have it said.

FP is in fact vastly superior

FP is in fact vastly superior to OO

FP and OO are two totally different things. You should better compare imperative and functional programming. OO is nothing more than a good (?) way to organize software (that, for me, has failed to do so as I've said in other threads).

The major problem with FP is the lack of existing software.

Yeap, that's what I've been telling all along here in LtU. Unfortunately, FP languages are far off mainstream languages, and people don't want to write software for the FP languages...it's a kind of chicken and egg problem (software is not written because FP languages are not 'accessible' enough, and FP languages are not successful because there is not enough software for them.)

When the majority of the software is built around the large collection of Java frameworks and libraries out there, you'll have a hard time explaining them just how making the switch is going to increase production. Management like to have options, and I don't blame them.

That's the reason why there should be a pure FP language with Java-like syntax and direct interfacing with C, with a central site containing the APIs needed for enterprises to do their businesses with (not scatterred around sourceforge / personal web pages), but I don't see any interest or response from LtU members on that front...:(. I understand it's beautiful to theorize about types and math, but if FP is truly worth something, we must do something about it.

Here, here...

I can't agree enough with the sentiments above. FP will continue to be mainly an academic pursuit until it's made to look more 'normal'.

The problem is what features to you put in your java-esque FP language? Linear types, monadic IO*, eval? Also how to you stop diversification killing it off before it has a chance to establish itself?

* A bit tongue in cheek, monadic IO would probably be a deal killer wrt more mainstream coders.

An unlikely hero rides to the rescue

Fortunately, there is a widely-used industrial language which while traditionally considered an OO language, is rapidly becoming a widely-used functional language. The language, once widely flamed by OO zealots for its alledged impurity, is enjoying a renaissance in academic computing circles. Unlike Java, this language provides:

* Decent generics, and well-designed collections
* Immutability as an interface construct, rather than just as an implementation detail.
* Better support for HOFs
* A value model for variables; unlike the reference model preferred by many other OO languages (which encourages aliasing of mutable state)

The name of this language?

C++.

:)

C++ does not cut it.

There are so many things in C++ that are wrong, that I wouldn't know where to start from. And I am a C++ veteran saying that :(.

I didn't say that C++ was an ideal alternative...

...it certainly has its share of warts, and then some. (Not to mention a tumor or two). The syntax is frequently ugly, it's STILL far too easy to subvert the type system (including accidentally), and the lack of GC is an issue for many. (Though GCC now ships with an optional garbage collector).

But it is a mainstream language with lots of mindshare, and thanks to the folks at boost.org (and others), it is oft programmed functionally.

Out of the ML/Haskell camp, probably the least threatening functional language (to the mainstream OO crowd) would be O'Caml.

The C++ mindshare is not on its functional features, though.

When people refer to C++, they think of OO. Without support for GC, C++ falls flat on its face.

I think that support for garbage collection should be part of the language specification, not of the compiler. Companies will not touch a compiler that uses a very important feature in only one of its versions. There are many reasons for this, including compiler vendor lock-in.

C++ as OO.

I'm not so sure. Currently the more favorable thing seems to be STL and template meta-programming for some reason.

Are you joking?

Are you joking? Most C++ programmers mock the STL and templates as unnecessary and complex.

Hey now.

When's the last time you had a job interview? :)

Times are quickly changing, for sure.

When's the last time you work

When's the last time you worked as a C++ programmer?

Until friday, I was working with some 10 different organisations, and I would say that the template programmers were in a minority.

Having Just Left a C++ Job of Almost Two Years...

... I'd say you're both right: there are those who really wish to leverage the STL and the functional paradigm, maybe even with template metaprogramming, and there are those who want nothing to do with it.

Also, and related to an earlier discussion, there's a difference between being a client of certain abstractions (e.g. I found myself using boost::bind a fair amount) and writing those abstractions (I wrote no template metaprogramming code in that time).

I would certainly say that if I were conducting a C++ interview at this point, the STL would feature in it. I would attempt to ensure that the candidate had a reasonable grasp of functionals, the standard binding constructs like std::mem_fun, and so on. It's not at all outlandish to expect a C++ programmer to know how to apply a function to all values in a container, or call a member function on all objects in a container, to know that "this" is an invisible parameter to a member function and always comes first, and so on.

I agree

I've just been through interviews with 4 big name software companies on the west coast of the USA. I've not used boost before and I was worrying that they'd ask about it. I got only one question that barely included a template in the solution.

yes

those C++ programmers known as C programmers with some OO.

features? the absolutely needed ones.

-functions as first class entities
-generics
-algebraic data types
-lists
-threads and typed channels

I think that's more than enough. IO should be free and the responsibility of the programmer.