Hacker News new | past | comments | ask | show | jobs | submit login
Is Haskell the right language for teaching functional programming principles? (profsjt.blogspot.com)
174 points by ingve on Oct 16, 2017 | hide | past | favorite | 219 comments

Beginner programmer here – I just want to say that I credit Elm with getting me hooked on programming. I tried other languages (Ruby, Javascript, even Elixir) but I never made it past the first project. With Elm, I've made a few projects and show no sign of stopping. Here's the best I can determine why:

1. Elm is simple, so I have fewer options to choose from when solving a problem. This means I learn a few ideas really well.

2. Even thought Elm is very much about the web (as the article mentioned), it's awesome to be able to see things in your browser immediately. It's also helpful to be able to build an application without a backend. You can see your model in the same file that you see your view, which helps you more easily think about each part together.

3. Complier/Type System: Once I finally figured out Union Types, the compiler is super helpful and friendly.

4. Elm forces you to handle errors, functions that can fail, and "Nothing", all things that you have to (a) know about and (b) remember to do in other languages.

5. Lack of tutorials, documentation and libraries to rely on means less "productivity" but it forced me to really learn the language and how things worked. I had to implement OAuth without a library, read source code to figure out what a function did, and couldn't google every problem.

I'm too new to know if Elm taught me the most important things a I should know about programming, or if there are better options out there. I do know that it's really fun. As a beginner, that might be the most important thing.

This is so true. Anyone who wants to see the ideas behind Haskell and It's style of languages succeed should be doing everything they can to support elm. You can't find and easier, more straightforward introduction to the concepts and style of programming than it.

Yes purists will complain about the bells and whistles it does have, and that's exactly the point.

You can learn elm and be productive in it in after a single weekend. And it's error messages should be the industry standard for language messages in any language. It's incredible how simple and accurate they are. It will change your view of what a compiler is capable of.

Not to mention it's not a far leap for people already doing web coding.

I would just like to mention that as of 1.5, Elixir has stepped it's game up on error messaging as well, to get as close it can get to Elm's(which truly are fantastic) without static typing.

The only thing I wish it had was something like ML's module system, with functors. Mainly, I think it would be a good thing for Elm to have because it fits so well with the Elm architecture.

Very interesting. How is the Elm documentation and examples? P.S. Trying out a few examples now.

Simple, yet felt quite sufficient. The language itself is simple and with the compiler errors you rarely feel stuck.

The official Elm slack #beginners channel is full of helpful people as well.

Thanks, good to know.

As much as I hate to say this, I think untyped functional programming is the way to go to teach about the virtues of functional programming.

We do this at my university using the obscure but awesome Oz programming language (1). But then students (and some professors, truth be told) complain that it's obscure...

If I had to pick one, I'd say Elixir. It's like Erland with less wonky syntax. Another option is a pure scheme. But people hate on the parens (yes, it's not very smart, but people are going to do it anyway).

Pyret (2) is also made for this purpose, but that's sort of the caveat: it's a teaching language and people don't like that.

(1) https://www.info.ucl.ac.be/~pvr/book.html (2) https://www.pyret.org/

I mean, you could use jq[0], if dynamically typed functional languages are your thing. It's probably not a bad idea, actually, since jq is so simple... (It's also quite accessible in terms of implementation, so it's probably a good platform for an entry-level CS language implementation course, but then, too, homoiconic languages such as LISP are even more accessible for such courses. Also, jq is fundamentally limited in that it does not and cannot have closures of indefinite extent, nor functions as first-class types whose values can be stored in objects of any kind -- so it's not really appropriate beyond an entry-level class.)

But I do think the Haskell family of languages is fantastic, and something to teach more, at least to math and CS majors.

[0] https://stedolan.github.io/jq

I think implementing a Lisp in Lua would be a great problem to learn functional programming with.

Above all, I'd like to learn Clojure. For whatever reason, it seems most of the Clojure devs I've met are able to spin more magic with the language than any other "type" of dev I've met. Plus I think Rich Hickey is a genius.

I haven't looked into Elixir much at all, are there obvious pros to using it over an older/more established functional language like Clojure or Scala?

Comparing it to Scala, it has a blazing fast compiler, is a smaller language with less ways to obfuscate code while still supporting metaprogramming. Also, you get all the advantages of the BEAM and OTP.

> We do this at my university using the obscure but awesome Oz programming language

I got exposed to Oz by accident, in school. This programming language is so obscure and the documentation so indecipherable, that we thought it was created as a mean of torture for new students. Luckily for us, our functional programming classes were using OCaml and it was awesome.

Really? I think the documentation is up to par: http://mozart.github.io/mozart-v1/doc-1.4.0/

Clearly, it's possible to do better. It's also possible to do much worse, and it is often done.

At least back in 2004, the Oz documentation was sufficiently problematic that I wrote a VirtualManual[1].

> Mozart/Oz has a lot of documentation. Many documents, papers, lecture notes, etc, and several web pages which list them. And subjects are often discussed in several documents. This page attempts to integrate the documentation, saying "for subject foo, see these n sources".

I expect the links are mostly rotted now.

The scattered fragmentation of the documentation was tolerable once you were familiar with both the language and its documents. But for new users, especially those without the Oz textbook, it was a serious barrier. Glad to hear it's now much better.

Thank you for the reminder of all this -- my anonymously-editable Oz wiki was still running, gathering unindexed spam. Static partial snapshot now. Activity moved to an official wiki a decade ago. Perhaps sometime, I'll look to see if any of its other pages, were also still linked to or used, or of possible historical interest, and restore them too. Thanks again.

[1] http://www.vendian.org/oz/wiki/index.cgi?VirtualManual

As an outsider taking a quick look I found it difficult to navigate. Guided by a course that can be fine, but without that I have no idea where to start. Compare that with the tours of D and go: https://tour.dlang.org/ & https://tour.golang.org

Oz is absolutely awesome. It's a shame few languages have inherited its ideas.

There's an upside to using an "obscure" language: everybody starts out on the same level. And with a multi-paradigm language like Oz, it's easier to teach a breadth of different concepts, since most languages tilt heavily one way or another.

Too bad about scheme, that's the language I used to learn functional programming and it seemed to make so much sense in that context.

I got in touch with Scheme twenty years ago. Read the specification (R5RS) and that was the first time programming in Lisp made sense to me. Because the specification was so short, I could remember every detail after a short time. Also the syntax was so predictable unlike Common Lisp with its myriad of operations. Without reading too many books about Scheme I started programming in it. Learned about tail recursion. About destructive vs non destructive operations. About functions that always returned values. Then I got in touch with SICP ("Structure and Interpretation of Computer Programs"). Man, that book was a revelation.

Scheme was a breathe of fresh air coming from C/Pascal/Java. It was a totally different way to tell the computer what I wanted to do (although I had similar thoughts several years earlier programming my HP28s calculator in a Forth like language, then later when I started using Mathematica).

Scheme is pretty alive and kicking, see "Racket".

LFE (Lisp Flavored Erlang) is also a good choice. The site has the beginnings of implementing SICP in it. [1,2]

I prefer J myself. [3]

  [1]  lfe.io
  [2]  http://docs.lfe.io/current/index.html
  [3]  jsoftware.com

Oz is a great language, good to see it getting some use. It's a pity it hasn't got more popular.

Haskell is really the intersection of functional programming and static typing at the highest level, and these are 2 very different things, and it will be very easy to get lost in the typing aspect for fear of not grasping the functional aspect.

If your goal is to teach just functional programming, then Haskell may be too much since the language is about a lot more than just functional programming.

Scheme or a light lisp (including Clojure) is often the way FP is initially taught, since you can focus directly on the functional aspects and leave the complexities of static typing out of it. This was the tradition at MIT for a long time (maybe still is).

Hackett (https://github.com/lexi-lambda/hackett) seems like an interesting project in this regard.

Yeah. I have to agree. The same was true for me with OOP, when learning it ages ago.

My feeling is Haskell is a bad teaching language for the same reason C++ is -- there is too much "this is some crazy stuff you have to learn about the language" early on.

One reason I have learned to love teaching Java over C++ is that the language-based bugs tend to be "shallow", at least in the first few weeks. The error messages tend to be easy to interpret, and when programs crash it is easy to understand why (how to fix it might be hard of course!)

For later year students, it's fine to expect them to learn the weirdnesses of Haskell and C++, but not for a student on day one.

> there is too much "this is some crazy stuff you have to learn about the language" early on.

There is actually not that much crazy stuff you must learn early on. The problem with Haskell is that it's hard for beginners to know what stuff they should avoid.

yes, especially when bloggers and conference talks show off that edgy stuff. People begin to get attracted to Haskell because of those things.

Things have changed a bit too over the years. I've heard of folks that burned out on haskell after wrestling with Arrows, and obscure arrow operators. Also, remember iteratees?

It's all in the approach. I've noticed most universities these days either get students started on Python or C. I believe the idea behind starting with Python is that most beginning students will hit the ground running, whereas the idea for C is that you get thrown in the deep end but will have a deeper understanding (and perhaps foundation) going forward. Which approach is better I dare not say..

C is good for teaching a simplified machine model, one with a distinction between stack and heap, pointers, and a purely sequential execution model. This is enhanced if you use it to program an Arduino or similar trivial hardware, collapsing the division between hardware and software to one piece of hardware (the single-board computer) and one piece of software (the code the student wrote) and nothing else.

C, in short, gives a good way to control actual hardware without having to introduce students to the complexities of actual hardware.

Python is good for teaching algorithms and OO design, precisely because it allows students to focus on the algorithm while not having to slow down the course with memory management.

In both cases, the idea is clear: Only teach one hard thing at a time, and then build.

I teach C as a second language. It is useful to learn from a historical perspective and because so much software is written in it, but I find it doesn't give that good understanding of machines compared to say java, and many of the problems are C specific.

By "C specific" I mean reading from freed variables, or going out of bounds in arrays. These bugs are horrible to find, but also don't map cleanly to the underlying machine, because often the compiler will optimise away invalid accesses, or move them somewhere weird, meaning you can't use your understanding of the real machine to understand the C bug.

I always thought it'd be a lot nicer to learn FP, without the static type system stuff, say in Erlang or Scheme, so students would be able to recognize the difference between the two.

I always thought FP was a cool idea but I couldn’t get started. Erlang was a revelation.

C++ isn't as crazy as the concepts in haskell.

I’d argue that you have to get pretty deep into experimental GHC language extensions to get into anything as weird as some of the SFINAE-based template metaprogramming tricks I’ve seen (and used, sadly) in C++.

Racket / HtDP is the best way to teach functional programming to beginners.


Haskell obviously has its place, but it is much better used when looking at something like PL Theory at a 3000-400 level.


Racket is an educational programming language as well as now a great general purpose language.

I tried to learn Haskell three times and I always left with a bad taste in my mouth. So many paper cuts in the ecco-system aka I HATED Cabal and I know they changed it but man that this was horrible.

Definitely agreed. I was introduced to functional programming via Pyret, which is similar to Racket and draws from HtDP in terms of pedagogy. It's a much gentler introduction than being thrown to the wolves with Haskell or OCaml. I'm sure one could learn FP effectively with those languages too, but if you're still trying to wrap your head around the functional paradigm you don't really want to have to stumble across words like "endofunctor" while reading the documentation. I even have a good math background but I would have found that confusing at the time.


Glad to see people are enjoying Pyret! If you don't like the parenthesis in Racket, this is the path for you.

Yes, I did the Coursera Racket course and it was great.

I wouldn’t think so. Maybe Clojure?

I kind of like Haskell but I’ve been turned off by the way some of the development is done.

There is, for all intents and purposes, only GHC. Yet everyone uses it by tuning on all sorts of special options to make it more usable. Why are they options? To remain ‘compatible’ with the ‘other Haskell compilers’ that basically no one seems to use.

It’s like if JS all defaulted to 1.0 and you had to pile on options to use any features after 1998.

It just makes things much more confusing and odd than necessary. To support something it seems like no one uses.

It will also be easier once the whole applicable/monad thing is done.

Clojure's focus, after simplicity, is functional programming.

Haskell's focus is as an experimental vehicle for type system theory. If you want to teach type system and category theory, use Haskell.

Functional programming does not require Hindley-Milner type inference, and that happens to be one of the larger cognitive hurdles in Haskell. Algorithm W is a layer on top of the Lambda Calculus, not something essential for understanding it.

+1 for using Clojure to teach Lambda Calculus^h^h^h functional programming.

Just because there are some folks that use Haskell for for experimental studies, doesn't mean that Haskell is not a great language for line-of-business programming.

I can't say it better than Gabriel Gonzalez:

"Haskell is unbelievably awesome for maintaining large projects. There's nothing that I can say that will fully convey how nice it is to modify existing Haskell code. You can only appreciate this through experience.

When I say that Haskell is easy to maintain, I mean that you can easily approach a large Haskell code base written by somebody else and make sweeping architectural changes to the project without breaking the code."

I think many of those special options will eventually become defaults once the Haskell 2020 standard comes out, which was started last year: https://mail.haskell.org/pipermail/haskell-prime/2016-April/...

You can follow along here: https://github.com/haskell/rfcs/pulls?q=is%3Aopen+is%3Apr

GHC is definitely the only widely used compiler, but there is at least one other significant one I know of: https://github.com/IntelLabs/flrc

But you describe exactly how I as a haskell programmer experience JS. I need 6 babel plugins and and a build tool to my ES6 to work...

Honestly I don’t do modern JS so I don’t know how much of a mess it is (or isn’t). NPM’s existence makes me lean heavily in one direction.

I only use JS on the front end for website interactivity and that doesn’t tend to be very fancy.

There is an effort to update the standard with the language extensions https://prime.haskell.org/

It's partially that. But the extension system is also there because it's a super light process to get them accepted, and the development community is voting in a way about what extensions are worth adding to the languages, and what can be left to spoil and die.

I get that. It just seems like every developer has a list of 15-20. They’re often different but the core few is ALWAYS there.

Every Haskell book I’ve seen (even those many years old) includes bits about how you should basically always have X, Y, and Z on and you don’t want to bother developing without them.

Seems like those should have become default long ago.

I get why some of that stuff exists in C/C++ land where people use GCC, MSVC, and LLVM among others.

But Haskell is practically a monoculture.

Good to see from sibling comments this is being addressed in the next standard.

Having learnt Haskell as my first programming language, sure it has a high learning curve but it pays off in so many ways. It is without doubt the most beautiful language ever conceived. Without doubt it is the right language to unlearn imperative bs and the right language to learn functional programming principles. Even against the likes the of lispy langs and other ml flava, Haskell reigns supreme with it's purity

It's the most "beautiful", and It's the most "pure" are probably reasons 99 and 100 on a list of priorities when choosing why a beginner should learn a language. Those reSons are reasons for people instilling why others want then to learn that language, not why it's the best for them to learn.

"It's the most pure" is a perfectly good reason to learn a language if you are trying to learn the concept about what the language is pure.

Of course, that completely flies in the face of an education system oriented towards training hordes of non-thinking peons into start positions at the job market. So, yes, it's not for everybody.

The question is about learning functional programming, Haskell forces you to learn much more than that to use it. Functional programming should be taught in something like Scheme, which lets you focus on the functional without being forced to also deal with a crazy Hindley-Milner type system that has nothing to do with functional programming. Haskell is not the right language to learn functional programming in, it's not the right language to learn anything in, beginners should start in easier languages.

> It is without doubt the most beautiful language ever conceived.

Only if you're a masochist.

Quite honestly, I feel if you think Haskell's beauty is somehow in any way associated with masochist mindset , you most likely think Maths is associated with a masochist mindset and (assuming math defines reality) the true nature reality is only viewable to those with a masochist mind. Then friend, I truly am a masochist

Yep :). I don't agree math defines reality however; it can describe reality, it doesn't define it.

I'd say Haskell is the right language for mathematicians to learn programming. Purity and laziness make Haskell definitions almost indistinguishable from mathematical ones; that means that the functional part of "functional programming" will come easy and you can focus on the "programming" part instead.

I'd agree.

It’s probably hard to see it this way when you’re starting out (and you may need a certain personality type as well =) but for me, programming in Haskell is a genuine pleasure because it’s so easy to express yourself in it. Things that require a huge amount of code in other languages are effortless and elegant in Haskell, and the compiler is extremely effective at finding mistakes in your code and often even your design, so you start treating it as a partner that helps you write your program. The experience always puts a smile on my face. YMMV, of course.

I do suspect that in the near term Idris may overtake Haskell as my favorite language to program in, though. I haven’t had a chance to sit down and learn it yet, but everything I’ve read about it so far has left me very excited.

I'd argue you're conflating simple with easy; the code might be simple, but I'd wager given the inability of Haskell'ers to even explain what a monad is successfully, that few would find it easy.

It has a shallow learning curve, if you use the term correctly. The graph of the amount that you have learned rises gradually over time.

It has a much wider learning curve than any other language I've met. You just keep learning, and learning, and at no point you feel like you master it.

Yet, it also has a much higher learning curve than any other language I met. As you learn and learn, your productivity improves again and again.

The learning curve also starts from a very low point. Without a few key concepts (no, not monads) the language is almost unusable.

The same could be said for something like Perl, where code gets a reputation for being only readable if you wrote it yourself because no two people know the same subset of the language.

That is probably an exaggeration, but it's definitely a problem you see in large complex languages with multiple ways to accomplish any particular task.

Haskell is typed lambda calculus and an amazing amount of syntactic sugar. One of the ten or so "aha!" moments of learning Haskell is realizing that so much of the language boils down to just \x -> let {...} in case {...}.

Which probably wouldn't be a bad way to teach Haskell, perhaps -- once one gets the general underlying form, understanding the rest is mostly just learning how the rest maps to that form.

No, it's completely different from Perl.

The core of Haskell is not that complex (although there is a lot of complexity on extensions). All the learning is in how to apply it, not on understanding the thing.

It is like OOP development practices, but wider and higher.

Perl, the only language where mashing the keyboard randomly has a 50% chance of working. I have looked at some of my old Perl and long-since offered my formal apologies.

I think there is also an emotional/social dimension to choosing a beginner's language that is important to take into account.

Imagine (putting Haskell's static typing aside), the difference in feeling between learning the basics of FP (say higher order functions, streams, all the different ways of dispatching function calls, etc.) in Haskell, vs OCaml, vs Clojure, vs scheme, vs javascript. Poking around on the internet, the beginner is going to get really different aesthetic vibes from each of these languages.

To shamelessly generalize: - Haskell/OCaml feels cerebral, academic, Mathematical, maybe even elitist - Clojure/scheme has that dark-terminal screen, classic 80s vibe- to me it feels nostalgic and quirky. - Javascript is, of course, javascript- it's bright, active, and, most of all, popular

All of these will bore/intimidate/comfort/excite different student demographics in different ways, completely independently of the programming concepts that you're teaching. So I think it's important to keep in mind the aesthetic preferences of the students you're trying to catch.

What do you think about Standard ML as a language for teaching?

I like it because the syntax is clean, it is functional and higher-order, but also has an explicit concept of references (i.e. mutable memory) and using functions with side effects (i.e. printing) is no trouble at all.

I have been programming for over 20 years, most of it in FP land. ML is tractable, a beautiful prism through which one can peek at Computer Science as a subject, but it has a frustrating lack of _practical_ tooling and beginner-friendly community. For anything outside basic I/O, you will need to dust off compiler-specific extensions, most of them last used on "Un*x Workstations".

Just look at the Basis library. Safe to say it's nowhere near Racket, Scala, Clojure, Kotlin, ...


Using ML trough ReasonML + BuckleScript and the related tooling should make ML palatable.

Alternatively, F#. That fixes the tooling issue pronto.

I never understood why a lack of tooling would be a serious problem for a language used for teaching FP.

It's a tough sell if the language has no hope of industry adoption. Also tough to use a language, especially one with type inference, without editor support.

Most people in my SML class seemed to have no problem with either of those.

Maybe some classes are just that good. A lot aren't, I'm guessing, and you would want to at least take away something you could use in the real world from them.

F# or OCaml then.

While I was already familiar with Common Lisp, SML gave me an appreciation for functional programming, as I worked through a set of lecture notes and examples that I found on a CMU website (apparently no longer available.) I am in no position to say that it is the best choice, but it worked for me (and the quality of the notes may have been an important factor.)

SML was my first exposure to FP, and while I didn't _really_ get it then, it was responsible for my initial interest in Haskell after graduation. I think SML is a great tool for teaching FP.

I second that. I followed an 8 week university course teaching introductory programming using SML and picked up Haskell on my own afterwards. I think SML helped me get enthusiastic enough about FP to motivate me to study the more advanced concepts

Standard ML would be a great beginner's language except for the weak beginner's guides and lack of support. Even basic printing to console can be agonizing in Standard ML.

Not really:

    $ poly
    Poly/ML 5.7 Release
    > print "hello\n";
    val it = (): unit

What about Ullman's wonderful book?

Robert Harper has written a few posts on his personal blog why they use SML to teach functional programming, why they teach it to freshmen, why they don't use Haskell ect https://existentialtype.wordpress.com/2011/03/21/the-dog-tha...

"Finally, this article explains why Haskell is not suitable for my purposes: the principle of induction is never valid for a Haskell program! The problem is that Haskell is a lazy language, rather than a language with laziness. It forces on you the existence of “undefined” values of every type, invalidating the bedrock principle of proof by induction. Put in other terms suggested to me by John Launchbury, Haskell has a paucity of types, lacking even the bog standard type of natural numbers."

I think Haskell is a beautiful language, but it's community seems too elitist and pedantic, which from my perspective makes people value sophistication and "elegance" over readability and ease of comprehension. I'd recommend Elixir, it's code is beautifully readable, it's pragmatically functional since it's based on Erlang, I'm not refuting Haskell usefulness in the real world, I'm just pointing out it's functional nature is academic, while Erlang's functional essence is pretty much a colateral effect of the problems it was aimed to solve. edit: Thinking again, even from the academic perspective, I'd still go for something like Racket, in my sense of aesthetic there's no competition to the beautiful simplicity of lisp.

Could you clarify what you mean by elitist/pedantic? I've found the Haskell community to be fairly friendly, and very open to beginners (including when they ask basic questions).

I've mostly been on /r/haskell and Quora, and watched talks by Haskellers though, so maybe the community is different on other platforms.

Well you got a point, indeed the actual community is really nice at a personal level, I was talking about the image of the language you get from advocates you see on random discussion boards and blogs posts, so my use of the term "community" was probably imprecise to say the least. And I remember having issues with documentation in general, there's usually a lot of academic jargon which is kinda unique to Haskell, monads is the obvious example but there's a lot of concepts that seem to be treated on a much higher level of abstraction that I think is actually needed to get things done, and I'm sure things improved since I last tried Haskell, but that's why I think Haskell is elitist and pedantic.

I'd say this thread is a perfect microcosm of it. In JavaScript, the general attitude is "you're right, this thing you're complaining about is kinda stupid, here's this tool to make it go away" versus "no, you're wrong, Haskell is great, STFU"

I don't think that's really true in the Haskell community. I've seen lots of self-criticism of Haskell on /r/haskell. Even SPJ himself is willing to admit that Haskell has design mistakes.

Some things Haskellers readily admit as issues with Haskell:

- the String type

- records

- laziness (more contentious, but many people agree that this might not have been the right choice)

- error messages

- the prelude

Essentially, my experience has been that Haskellers are willing to accept that Haskell is not perfect.

Indeed, the Haskell community is very self critical, much to its credit.


I learned FP using Racket. It was a good experience, but the parenthesis were really annoying. It makes you feel stupid.

I believe Elm would be better choice. It would allow to get a visual result easily (html), there is a clear convention about code formatting and the compiler errors are really friendly.

I think Haskell is very akin to C++ in terms of learning curve.

There are a ton of concepts you have to learn up front to even get started. The compiler is generally unhelpful if you've never dealt with it before. There are a lot of approaches to solving a problem and the language does not make it clear which approach is preferred when. Unless you're a masochist, these qualities can be quite off putting.

I think a language like OCaml is a good entry point into functional programming. The compiler errors are really useful. The language pushes you towards a sane functional approach. The learning curve is pretty smooth, too.

My alma mater seems to agree and FP with OCaml in the upper level CS intro course (https://www.seas.upenn.edu/~cis120/current/index.shtml).

My path to functional programming started with Paul Graham’s lisp essays and books and then SICP and Scheme. I visited the world of Haskell but only half heartedly as I was much happier in a dynamically typed world for my hobby projects. As a daytime C++ coder I found types an annoyance; so much time wasted getting something to compile. Later I came to discover types again with Scala and now I’m fully sold. I will revisit Haskell again some day but most likely will learn Elm first. Elm is a much friendlier ML style language and much more explicit about things like monads. Moving from Elm to Haskell is much easier since the programmer will have “aha” moments mapping what they did explicitly in Elm to what you can do more generically with type classes in Haskell

I'm lucky enough to own copies of On Lisp and ANSI Common Lisp. These books are a pure pleasure to read -- a lot like reading a novel.

May the warm light of Lisp enlightenment shine on you -- CL blew my mind!!

I strongly recommend these two books. They are amazing!

I love Purescript, but I think in some ways it is even more arcane than Haskell for a beginner.


    > :t (+)
    forall a. Semiring a => a -> a -> a
    > :t (&&)
    forall a. HeytingAlgebra a => a -> a -> a

Agreed on both points, love it and a bit too wicked for new-comers. Elm is perfect there and should find its place into all kinds of educational contexts hopefully. Such a friendly ML language, I secretly call it "the Basic of FP/ML land" (an honour in my book; more modern equivalent might be Python there but you get the idea).

Also good that it's missing "advanced" stuff like type-classes, built-in monad/functor/applicative & friends. Good for teaching because students will be compelled to learn to write that themselves from the ground up. It's all lambda calculus under the hood anyway, and thusly representable "hand-made from scratch".

But it requires a different kind of skill altogether. A semiring is a concept in abstract algebra that’s quite independent from general functional programming.

That's kind of my point. Usually when you're just learning "general functional programming", you're thinking about, say, (+) as a function that takes two numbers, and returns a number, because you're at the stage of figuring out how something like

    fold (+) 0 [1,2,3]
works. Introducing "Semiring" as a concept at the same time can be a bit much for a beginner!

I do think it's a useful concept, and that Purescript is an excellent, intermediate-level FP language.

I do believe that Haskell is the wrong language to learn functional programming principles. Right off of the bat Haskell forces learners to use monads for IO. Monads are an advanced concept; too advanced for beginners. If learners end up do kind of getting the IO monad, a big number of them actually end up not being able to understand why it's good or even understanding what a monad is completely... and see it as a pointless overcomplicated abstraction. I knew a person who learned Haskell then moved on to javascript due to the wall he hit while trying to understand monads. I've looked at his javascript code and his idea of functional programming is just littering his imperative javascript code with maps, reduces and filters.

Thanks to redux, a lot of people are getting a broken view of what functional programming really is via javascript. If you think you've learned functional programming via react/redux and javascript... chances are you haven't really understood it yet. Ask yourself, why is functional programming called functional programming and not called immutable programming? If you don't know the answer... you haven't really grokked functional programming yet.

The right language? Racket maybe?

I disagree that you have to learn monads for IO. I know some tutorials mention monads right off the bat while teaching IO but that is not a recommended teaching approach.

For IO what you would need to learn is that all IO actions are values of the `IO` type and they can be sequenced together for guaranteed ordering using the `do` notation. That's it. No monads. We can introduce monads after we show using the same `do` notation for lists, `Maybe`s, and `IO`.

>For IO what you would need to learn is that all IO actions are values of the `IO` type and they can be sequenced together for guaranteed ordering using the `do` notation. That's it. No monads. We can introduce monads after we show using the same `do` notation for lists, `Maybe`s, and `IO`.

This is an awkward teaching approach. Forcing learners to use advanced concepts without fully understanding them. Why can't haskell just have a print function that returns a void? How come when I use haskell with input it starts polluting the input with this IO thing? This all seems stupid initially and it takes a lot of learning to understand why things are done this way.... I mean that person I know thinks javascript is better than haskell because console.log("hello") is ten times more straightforward.

I disagree that it's forcing learners to use advanced concepts. It's giving them syntax sugar and a fairly clear introductory explanation (IO is done only with the `IO` type for safety reasons) and giving them all the capabilities of IO in other languages straight from day one.

Forgetting about types for a second, can you really say that `putStrLn "hello"` is harder to understand than `console.log("hello")`? Trust me when I say this, plenty of people have taught Haskell to kids and the result has always been that they pick it up easily. Programmers from other backgrounds worry away too much of their mental capacity thinking about monads. Stop worrying about it and just hack away.

Understanding a pattern is different from copying a pattern. Our disagreement lies not with kids copying a pattern but with people fully comprehending the philosophy and true nature of the monad abstraction. This is not easy for a beginner. Allow me to elucidate:

Here is a an example of a trivial operation in imperative programming that becomes a bit more complicated in Haskell: Create a function that prints everything in an array:

naive implementation in haskell (won't work):

  printElements arrayOfStrings= map putStrLn arrayOfStrings
  main = printElements ["Hello", "World"]
True implementation:

  printElements [] = return ()
  printElements x:xs = (putStrLn x) >> (printElements xs)
  main = printElements ["Hello", "World"]
The second implementation requires understanding of types and the IO monad while the first implementation is a naive and broken implementation that most people turn to when learning Haskell.

It is not trivial to explain to a person why it must be done the second way... All of this and all we were doing was printing something to the console! It's too much! Monads aren't even a required part of functional programming. Haskell is not a great language to learn about functional programming.

Actually the "true" implementation is

    printElements arrayOfStrings = traverse putStrLn arrayOfStrings
    main = printElements ["Hello", "World"]
but the difference between map and traverse is sufficient for your point to still hold water.

I think we would actually use `mapM_` rather than `traverse`.

Or rather `traverse_`. (I still don't know why `traverse` is not renamed `mapA`.)

Interesting, I don't see `traverse_` in Prelude in 8.0.2 that I have on my machine.

It's not in Prelude, it's in Data.Foldable.

That's a good point. But it actually goes back to my previous point that we need to teach that multiple IO actions need to be sequenced together to guarantee proper order, hence you can't just map a print operation over a list of items--and in fact the type system prevents you from making that mistake.

As I mentioned before, I would stick to the do notation syntax sugar; there's really no need to bring the symbolic operators into this:

    printElements [] = return ()
    printElements (x:xs) = do
      putStrLn x
      printElements xs

do notation sugars free variables which leads to more confusion and more complexity. It may not be idiomatic, but I avoid do notation for this reason. It's almost a backwards abstraction... if the functional style is really better... why create syntactical sugar to make haskell seem imperative?

You guys are right on traverse or mapM though.

Yes, we have to walk a fine line here. The fact that do notation desugars to function calls in a complete deterministic way is nevertheless not easy to explain to learners. It's a judgement call but overall its benefits outweigh the drawbacks--IMO.

Java requires you to understand class and public static void main (and classpath crap) before you can print to console, but that doesn't seem too hard for anyone to learn.

The concept of an object is trivial compared to a monad. Objects in the computing world have real world equivalents. The real world equivalent of a monad is a burrito.

That is no way in which I can agree with any of that. An object is a rather poor analogy for a real world entity. Real objects don't need to have methods declared on them, they arise naturally from its state and from interactions with the state of other objects. Dogs don't have "wag tail" methods. Dogs don't have "name state" they are simply called names by people and have the facility to recognize their own name.

And as a poor analogy, a monad is also quite trivial.

Objects all have state and certain behaviors attributed to the object. In common OOP vernacular this is known as state and methods. A real world analogy is a ball that can bounce and also has a bounciness coefficient, the ability to bounce is the method and the bounciness coefficient is the state. This makes sense.

A burrito is a monad. Explain this.

I'm very interested in FP but I'm a sysadmin, not a dev, so I had to do a lot of reading. My conclusion is racket would be good for teaching indeed, but I think its ecosystem is a bit too academic though it is getting better. Instead, I think I would offer guile scheme as a language with some good, active projects to help on, such as the new cron replacement mcron.

I would probably also offer elixir and some lisp variant. It was actually lisp that got me so interested in FP because I saw how much it was being used in AI research.

That said, I think its worth noting Haskell is the only one I've seen listed here that is pure FP. So if one wanted to really use FP, it might be worth wading through the maze like Haskell ecosystem, but I don't think for teaching.

Absolutely not. You need a gateway drug before Haskell becomes interesting.

It's one of those things where you should not use a solution to a problem until you understand what the problem IS. Otherwise you'll feel like things are complicated for no reason.

ML, Elm, Elixir, Closure or even (yes, really) JavaScript are much better places to start.

I think you mean Clojure, not Closure. The latter is a library by Google.

Yes, Clojure :) I wasn't even thinking the library, but the programming concept when I typoed it. Whoops!

I have taught FP to more than one thousand students over 5 years. For all of them, the language was OCaml (at several universities, in Paris).

At the time and still today, I think that OCaml is a very good language to learn FP. Students that learn FP before any other programming language get it quickly, and others can compare and write both the imperative and the functional form of a given program. But as a whole, the installation is easy and uniform (which matters a lot when teaching) and the standard library sufficient for everything, as you never want to have a lot of dependencies for the same reason.

Of course, OCaml has its drawbacks: A weird syntax, terrible tooling... but you don't really see that when learning programming concepts. The only students which complained were the ones which already spent a lot of time programming before class and trollers at the same time.

For dismissing syntax complaints, have you looked at ReasonML?

Haskell syntax is terse but not simple. Not good for teaching Functional Programming PRINCIPLES. See: https://www.haskell.org/onlinereport/haskell2010/haskellch10... .

How about using Lisp to teach functional programming? Lisp syntax is small, simple. You don't need to teach so much Lisp as teach with Lisp.

Given your constraints, I'd say that Elm is an excellent choice. It's simplistic enough to be approachable, the easy web integration is a feature (not a drawback as you mentioned), and people are doing "real work" in Elm so they will be able to use it for years moving forward.

This question leaves me with more questions. The post looks at a few alternatives without giving context.

1. How does the course fit the overall curriculum? 2. What is the experience and maturity of the people taking the course? 3. How strong are the teaching skills of the instructor?

The density of functional features taught in a certain time period matters. A drastic change in mindset simply takes time that, I would say, is greater than a standard semester. A single semester is fine if FP is going to be reinforced, thereafter, in other courses.

Also, starting students with FP instead of imperative or OO means less to break down and relearn.

I've read numerous debates that try to define functional programming. I don't want to start another one because they're tedious. My experience is that functional programming is a change in mindset in how to solve a problem and organize code. The instructor's ability to teach matters. The time given to learn matters. Reinforcing the concepts throughout a curriculum matters.

For each point I make above, you could make a valid case for a different FP language/ecosystem. As much as I like Haskell, it's not a "one size fits all".

I learned Haskell in a course called "Comparative Programming Languages" by Cormac Flannigan (https://users.soe.ucsc.edu/~cormac/) my last year in college, so I had done a lot of procedural, object oriented programming by then, but no real emphasis on functional and especially not purely functional.

It was probably my favorite course I took in college, owing a lot to his outstanding teaching style. It awoke an interest in programming languages and a strange fetish for the beauty of them. I was probably the odd one out, few other students enjoyed it as much as I did. I became a slightly rabid Haskell promoter for a little while. I realize it's not great to build most things in but I think everyone should have the same experience I did with it (after learning some basic programming and gaining a working knowledge of at least one "easy" language like Java or Python, but before you've spent too much time with them and have solidified your opinions).

In my personal experience: No. I tried Haskell and Scala multiple times but never worked. Once I got to elixir everything just sunk in and felt easy. YMMV

Buy this: http://haskellbook.com/

I tried LYAH and some other sources a few times, but was really turned off by those approaches. It wasn't until i found HaskellBook that I really started liking it.

I think a lot of it depends on the background of the person learning. I came from a strong math/stats background before I learned to code and so much of it clicked a lot better than other imperative languages.

I'm currently learning Haskell from "Haskell Programming From First Principles"[1] and enjoying it so far (even attending a local weekly study group). I'm absolutely learning functional programming principles and then some. Pretty effective thus far, and I find it extremely accessible.

[1] http://haskellbook.com/

I've mostly learned functional programming with SML at university, and then I learned Clojure with no problems, and after that I still had problems with learning Haskell.

So I'd say - no.

I especially had problems with searching for varios operators and what exactly they do. Also (despite having some experience with SML) - currying makes function definitions hard to read.

I have never seen an operator that I couldn't find with Hoogle.

E.g. for (&&&): https://www.haskell.org/hoogle/?hoogle=%26%26%26

You can also search by type: https://www.haskell.org/hoogle/?hoogle=%3A%3A+String+-%3E+IO...

It worked for me, but I guess (also based on comments here) it depends on personality. I like to learn (work things out) from theory and I generally prefer to learn elegant languages that introduced some concept rather than a watered down version of that concept as it was adopted in more pragmatic languages. Some other people might prefer to be more practical and understand the theory later, and so prefer languages that are more pragmatic before they accept a new paradigm.

Haskell, due to its annoying insistence on pure functions, made functional programming click for me. I have seen functional style in impure languages before (Common Lisp) but I didn't have the discipline to really code that way - I only saw the downsides. Haskell forced that discipline on me, so I could also see the upsides. One significant upside is that one is forced to make functions really small, which leads to more readable and composable code.

Haskell itself is difficult to understand unless you give someone to read "Learn you a Haskell for great good". I was giving this book to my junior developers to read for understanding such principles like recursion, list manipulation functions like map, filter, reduce etc. and it worked pretty well.

SICP in Scheme is the only true answer. You are all heretics.

I actually enjoy the benefits of my course in Clean at university ( http://clean.cs.ru.nl/Clean => "Clean is a general purpose, state-of-the-art, pure and lazy functional programming language"). While challenging, it taught me all the functional principles. Many of the language features and principles can be applied and useful for understanding Python, Scala, Kotlin, etc.

Applying it to something that wasn't just plain 'ol boring was slightly hard, but creating soccer team logic as the final project with a pre-written GUI module was lots of fun. Before that I never thought exams that required writing actual code were a good idea, but this one pulled it off well.

Why not ML? Our programming languages course had a unit in ML and the transfer to Haskell after that was not trivial but still a smooth learning curve -- I could read not just getting-start or for-beginner guides.

One might consider using a functional language which isn't lazy. Haskell's laziness makes its behavior harder to understand and is not necessary to illustrate the core concepts of FP.

Not entirely on topic, but related, I have an evolving attempt at introducing programming language concepts by building a forth-like language in JavaScript - https://github.com/srikumarks/nospoon

It is written in a stream-of-thought literate style. Feedback welcome as issues.

Use a good _library_ of persistent immutable data structures. In any language your audience is already familiar with.

Functional programming is not just about using immutable data structures.

I had an FP course on F#, really liked it.

Haskell Type Classes are brilliant. But I would recommend a strict evaluation language like ML (and modules with signatures) for Semester #1 and lazy Haskell for Semester #2. Anyone could cover a ton of useful contextual material taking just a little more time.

I'm in the boat of learning FP right now. What would really help me, and folks in the same process, is for people to suggest languages that _would_ be better, and why, instead of doing the stereotypically HN commenter thing that I'm already seeing.

I always recommend https://www.coursera.org/learn/programming-languages for learning FP, the professor has fantastic explanatory videos that are really clear and concise. You'll get the most out of it from doing the exercises, but you can still take away a lot from just watching the videos.

Thank you. I'll check that out.

Probably not, because it's lazily evaluated and almost no other language is.

> Full disclosure: at Kent, after teaching Haskell for many years, we currently a compulsory second year course on “functional and concurrent programming”

s/currently/currently dispense/

We were thought functional programming with Dr. Scheme and Miranda. I think they were ok. Never had any problems with them. Have no idea about haskell.

> Have no idea about haskell

Born as a non-proprietary Miranda alternative, but instructors would have to be careful to side-step various modern quirks across the libs ("SQL as a free-monadic-profunctor-optics" and such broohaha) for a similar teaching experience.

Is there any other language with purity, laziness, and static types that could possibly be put forward as an alternative to Haskell?

Functional programmers practice a form of no-true-Scotsmanism wherein type and category theory are an intrinsic part of "true" functional programming. So unless you are working in something with a type system at least as expressive as Haskell's, you are -- arguably -- not doing true functional programming. (Sorry, Schemers.)

I knew the answer after just reading "Is Haskell the right language..."

Go SJT! He taught me haskell back in 2003 - rotating ascii horses

I think Python is a wonderful language to teach functional programming since it is so accessible for many definitions. One has to go a little off the rails to get all the functional features, but it is possible.

I also suspect this makes sense for an introductory FP class (FP, not static typing). The students have already already met the language, and they can compare functional and imperative styles of solutions to the same problem. I think I’d go with python, and then have one or two lectures near the end showing a language dedicated to FP / static typing.

Yeah, and by using a widely available language, they can actually use these techniques in the field.

No. It's a great way to turn people off from the whole idea.

I suffered through a course in Haskell and functional programming in college, and the course material was so up its own butt about monads and type classes and algebraic data types and such, that I essentially wrote the whole thing off as academic flubbery. It didn't help that whatever version of GHC we had then gave off error messages more cryptic than C++ template metaprogramming, and it was such a cluster to have to bounce into the IO monad to just to do some intermediate printf debugging.

It wasn't until years later and exposure to .NET LINQ that it started to click and the motivations for why you would want to use functional programming became apparent.

I studied Haskell in college (with the Gofer variant), and it was GREAT for learning practical functional programming.

We didn't use monads though (they weren't in widespread use back then), so we had to learn the accumulator-parameter pattern and tail recursion the hard way.

Learning my foldr's and foldl's and zipwith's gave me confidence that almost any imperative programming can be equally represented as a recursive function, which is an important lesson for someone who had only learned about traditional imperative programming and OOP up to that point.

Of course, a proper course should center around algorithms and recursive data structures where functional programming shines; it should not begin with building business application logic, for which a classic language may have a gentler ramp-up.

If your course didn't cover monads, it was a very introductory one which would have probably benefited from choosing a nicer and simpler language, like antiquated LISP or maybe Scheme.

> antiquated LISP

By that do you mean "Lisp, which is antiquated", or "a LISP which is antiquated"?

Lisp certainly isn't antiquated, but as the second oldest high level language after FORTRAN, there are antiquated versions of it (e.g. LISP 1.5).

Wadler's introductory Haskell course at Edinburgh doesn't cover monads, but it's great. I don't want to use scheme because I want students exposed to a decent static type system. There's an argument to be made for using standard ml, maybe.

I think the fact that strings are linked lists is great for beginners. One of their assignments is on web scraping, where they can reuse all their list based functions to solve the problem.

I am not too keen on Haskell's polymorphism for teaching beginners, and error messages are mostly useless for them. If I were teaching again, I would be recommending custom preludes with simpler types.

It was introductory, yes, although it also covered relational programming in PROLOG.

I benefited from the type inference/type declarations, and learning about generics explained in a non-duck-typing way, though, which I wouldn't have had in LISP.

Hey, can you point to or do you have any of the relational/Prolog programming materials? I dabbled in this years ago, mostly experimenting on my own, would love to see some materials designed for guided exploration.

I'm afraid the material is some handwritten notes in Spanish, interleaved with some code examples in PROLOG. They were quite systematic IIRC, covering basic logic, data structures, proper use of the !bang for performance, etc.

I no longer have the exercises in code, just paper. I've yet to scan my handwritten notes and bring them to the digital era :-) This may prompt me to finally do it.

If you still want them, I can send you the scanned pdf to your mail. However, I think you'd better off with some free online course. On a cursory examination, this one seems similar to the content in my notes:

[1] http://www.learnprolognow.org/lpnpage.php?pageid=online

There were courses using haskell before monads were the smash hit they are now. In particular haskell didn't have monadic IO then. On the other hand, variants such as gofer were pretty simple.

> antiquated LISP

That's debatable. True, Lisp is Old. Hardly antiquated.

I agree, but over the decades LISP developed significant complications, such as object oriented features; I think the most appropriate LISP for an introductory FP course would be a very antiquated and very simple and pure one, without advanced features (and the accompanying syntactic pollution) that might be of interest as advanced theory, useful in advanced practice, but a source of confusion and a major waste of time for beginners.

Fancy LISP variants would still be vastly easier to learn than Haskell, but a straightforward computer adaptation of lambda calculus would minimize the distance between theory and running programs.

I'm not familiar enough with Scheme or Clojure to tell whether they are too complex for an introductory course.

>I agree, but over the decades LISP developed significant complications, such as object oriented features

How can this be a complication? On Common Lisp, you can just choose not to use object oriented features (the CLOS system).

There are many CL libraries that do not use OOP code at all.

And if you want to use them, in CLOS a method is called exactly the same as a function; they are called "generic functions", so the syntax is just the same.

>without advanced features (and the accompanying syntactic pollution)

I don't think there is any syntactic pollution. Again, in Common Lisp the syntax is totally uniform for all the features, in fact for a beginners' Functional Programming course, he/she would only need to learn:

    () parentheses for opening and closing an s-expression
    ; for comments
    ' for quoting an s-expression so it is not evaluated
    #' for indicating that the following symbol 
       is a function name
       (not needed on Lisp-1 languages like Scheme)
    "" for delimiting a string
... and that's it!!

"Advanced" features don't introduce too much syntax either:

    `  for quoting an s-expression in a "template" way
       (i.e. for use in macros)
    ,  for escaping the ` operator
    ,@ for escaping the ` operator, "splicing" the
       contents of a list; for example when passing a code
       block to a macro.
For a language that is really extensive in features, the amount of syntax introduced is minimal, really.

Compare with Haskell.

Of eight special delimiter character you list, three are used for macros. While the syntax of the highly evolved Common Lisp you have in mind remains extremely frugal, macros are only one of many relatively large unnecessary luxury feature.

Teaching fancy language features in an introductory course steals time and attention from fundamental functional programming principles. CLOS, unless thoroughly dissected as an advanced example of how far can you go with LISP, would be an even worse gratuitous distraction than macros.

Of course, "complex" LISP isn't going to be comparable with Haskell, and in a sufficiently long introductory course advanced language features might be worth teaching to increase student productivity.

> I'm not familiar enough with Scheme or Clojure to tell whether they are too complex for an introductory course.

Simple Scheme has been used for decades for introductory courses, both in schools and university.

An even simpler Lisp called Logo has been used with early programming education for kids.

Lots of educational material based on Scheme or Logo exists.

I tried learning Haskell by reading LYAH and doing some of the cis194 course, it was alright, but I was struggling. Then I bought Haskellbook (Haskell Programming from first principles). Took me a while to finish it, but I had a great time doing it. I learned Haskell and was able to jump right into writing my first library with it. And I come from a non-CS background with only a bit of Ruby prior to that. The quality of your learning materials matters a lot.

I'm about ~300 pages into it and it's been really enjoyable. "Pure functional programming without fear or frustration" is so right. I've started to look forward to the couple pages I get through each day after work, it's legitimately relaxing.

It's great but also 1300 pages (and $60, well-deserved).

I enjoyed learning Haskell in an optional advanced course at our uni. The things which I like the most are higher order functions, playing with pointfree, combinator libraries, typeclasses, pattern matching and higher order types.

Only later did I click with monads and some other patterns like phantom types and such.

I think the sad part about learning Haskell is that everyone gets so up about monads while they definitely aren't the most important part but only one of many beautiful and magical parts of Haskell. Maybe if people stopped talking about monads so much and more about other parts of the language would people be way better at learning the language.

> they definitely aren't the most important part

They are that small piece that makes everything fit together and work. If you ignore it, you will have many problems down the line.

Yet, you are right, they aren't all that interesting by themselves.

While I agree that many courses on Haskell are no good ...

>> "up its own butt about monads and type classes and algebraic data types"

Well, those are some of the best things about doing functional programming in languages that can afford them.

>> "I essentially wrote the whole thing off as academic flubbery"

And maybe it was your attitude to the whole thing.

>> "It wasn't until years later and exposure to .NET LINQ that it started to click..."

So seriously, can't you find anything else that changed "years later"? Haven't you changed? Aren't we talking about years of accumulated experience?

Also, .NET LINQ might be a cool example of what you can do with FP, there are elements of FP in it, certainly that's a monadic interface that makes it tick. But filtering an IEnumerable or an IQueryable is as interesting as executing an SQL query.

What have you learned about FP from executing SQL queries? Probably nothing.

Just saying.

Functional languages and strongly typed languages are not the same set. Most functional languages focus on typing (e.g. Haskell, Scala), but there are functional languages that do not (e.g. Clojure, Common LISP). You can easily do functional programming in clojure without using any monad concepts directly (though obviously it’s easy to say “that’s just a monad” in a lot of cases).

IMO the biggest win from functional programming is referential transparency. Automated verification (i.e. type checking) can definitely be useful on larger projects with bigger teams since it’s self documenting. That’s just my personal take on it though - there’s plenty for everyone to like.

You're mentioning Clojure.

Clojure has protocols which are probably inspired by type classes. Just like Clojure's protocols, type classes are a mechanism for ad hoc polymorphism that allows decoupling between data and the functions operating on that data.

Clojure indeed doesn't have monads, but this has to do with Clojure's culture (like all LISPs) of using macros for describing APIs for composing stuff. But those APIs aren't unified and some of the DSLs I've seen do not have a theoretical foundation, which really means they aren't reusable and some of them are flawed.

Due to its evolution and backwards compatibility concerns, some of its design shows its age as well. You can't make operations like "map" work on your own data types because it doesn't have a protocol defined for it.

Don't get me wrong, I actually like Clojure, but that the community is not using types like monads to drive their design is a flaw.

What do you mean by "doesn't have monads?" You just write monads in Clojure. They are only a structural formalism. [1]

If you meant doesn't have the Maybe monad built in... why would you want that tangled up in your data? [2]

  [1] https://github.com/khinsen/monads-in-clojure/blob/master/PART1.md

  [2] https://youtu.be/2V1FtfBDsLU?t=2381

There are two important functional programming concepts absent from most Lisps: currying and lazy evaluation, so if a Lisp is used they'd need to be explained separately. Implementing them in Lisp would be a good way of understanding them.

If you want a more typical functional language without type declarations or monads, there's SASL. It's an ancestor of Haskell, but I don't know of any implementation which runs on modern hardware. Interestingly, SASL was once used to write an operating system.

I would hardly identify lazy evaluation as a core feature of functional programming. It definitely forced Haskell not to compromise on purity but, as SPJ himself has pointed out, that may be the only strong thing it has going for it[0]. Currying is also nice, but I'm still not sure that is _core_ to FP.

What Lisp is really missing from an FP perspective is purity. In fact, maybe a pure variant of Lisp would be perfect for teaching.

[0]: https://www.microsoft.com/en-us/research/publication/wearing...

Purity isn't missing. It's what you have until/unless you introduce/allow impurity into your code.

How can you even teach what purity is, if it is enforced?

"Bad things could happen, take my word for it?"

Isn't Scheme pretty darn close to a pure and clean version of Lisp? Which is why it was chosen as the language of SICP?

Hey hey and what do you know, you can do both in scheme!

ML-style FP (including Haskell) is probably the most blogged-about, although I'm not sure it's the common used style of FP.

Lisps, Erlangs, and APLs all have distinct takes on what it means to be "functional".

For example, J is dynamically typed, permits mutable state, and doesn't really have first-class functions in any meaningful way. But it definitely has a functional "feel" to it (easy to compose functions, almost all operations are side-effect free, etc).

Your arrogant dismissal of a beginners' genuine troubles with a certain programming style is exactly why programmers in general but especially the FP crowd have such a bad rep.

After having my fair share of attempts to teach people and hearing the same flawed arguments repeated online ad nauseam, including the "too academic" classification which ends all reasonable dialog, to be frank, I couldn't give a shit.

If you want to point fingers, I would be more worried about the rampant "anti-intellectualism" going on in this industry, accumulated along with other social problems (other -isms) we are experiencing, like sexism or ageism.

Look, it's fine if you don't understand, it's fine if something is out of reach relative to your current knowledge. And most often than not, the teacher is the one doing a poor job at teaching. There's a big difference in results between good teachers and bad teachers, between good books and bad books, etc. And maybe you don't need the subject in question, maybe you're fine with writing dirty Python scripts, whatever.

But dismissing work of other people as "academic flubbery" is mean and counterproductive and you can't teach people good manners — they should have learned those in their first 7 years of their life.

I'm also not inclined to fight for every beginner, I'm only fighting for those with good manners and if you'd know me, you'd know that I have open source libraries released and that I'm helping users in my free time and at great personal sacrifice. I'm actually putting my time and money where my mouth is and I've never berated anybody for not knowing something, only for being disrespectful.

The disrespectful ones can go somewhere else. I'm fine with having small and focused communities btw, instead of a big and toxic one, because life is too short to take abuse from random folks on the Internet.

I suspect that the complaints of "anti-intellectualism" are too general. Critical-theorists make the same set of complaints. There's a big difference between anti-intellectual and anti-bullshit sentiment.

When bad ideas are dressed up in academic authority, well they often have a hard time outside of academia. That's what "too academic" means. That this could be another bad idea dressed in academic authority and we'd have no way to tell.

> What have you learned about FP from executing SQL queries? Probably nothing.

I would really like to know why you conclude this, because it seems almost certainly wrong. SQL is a great example of a mainstream non-imperative, no-implicit-side-effect language, which is really the essence of functional programming.

Agree. Functional programming made no sense to me until I came back to it after years of writing complex data warehousing SQL.

I am writing SQL/PLSQL for my living and I like how learning Elixir changed the way I accomplish my daily work.

Hmm, I'd argue the essence of functional programming is composability of which SQL has very little.

I would argue that you probably haven't written any SQL of significant complexity in which to observe its composability if that is your assertion. Subqueries, table-valued functions, SProcs that return tables, and more allow you to compose operations into your desired final query.

That said, it is largely used in a giant procedural way most of the time, and is certainly not an ideal functional language, but the fundamentals of things like, map, filter, reduce, sort, etc. are there.

I have written quite a bit of SQL including all of the items you mentioned including common table expressions, subqueries, views, etc..

This is a very limited form of composition. It's very difficult to break a query down into a bunch of subcomponents that can be reused among groups of queries. CTEs are close, but it's really hard to achieve re-usability of a CTE unless you are stitching together strings at runtime.

Probably the closest you could get is a view, but even then if you have many views stitched together to form a query this can impact performance in ugly ways.

Generally in order to achieve the best performance and to get the most of out of the DB engine it seems like producing unique SQL for each query which is optimized for that query is generally the optimal approach.

In summary: Just because SQL is based on a few composable operations (map, filter), does not mean it is composable itself.

This is a slightly snarky but mostly serious response: isn't hidden runtime complexity of elegant operations also a property of functional programming languages? :-)

There are a few that are good at optimization (and in my limited experience, Haskell is one of them), but in general if you use lots of conceptually clean maps and filters, you will occasionally see cases where your performance is very bad because you don't have full control over exactly what is evaluated when, won't you? That seems like basically the same problem that you have with using views and not trusting your query planner to do things efficiently.

I can largely agree with that from a practical perspective - I was speaking more in the theoretical. At any kind of practical scale, everything does seem to end up being fairly bespoke.

With unsafePerformIO you can do printf anywhere. There's also Debug.Trace.

I had the opposite experience, but I used Chris Allen's book instead of a university course. A lot of concepts I had been using in Elixir and even JS did not click until I worked through Mr Allen's book.

Chris Allen's and Julie Moronuki's book, to be precise.

Thanks. Wish I could edit my comment!

I agree. Functional programming should not be viewed as a tuxedo that we dust off and use when we want to be "fancy programmers." It's simply a tool in the toolbox.

The best language for learning functional programming is the one that de-mystifies it. And since you can use many (most?) popular languages to code in a functional style, I'd say, take whatever language the students have been using, and teach them a few functional programming techniques with it.

Totally. A couple books that I've really enjoyed (being somebody that lives in DotNetLand)



1000000 times this! I learned FP (Functors, Monads, Applicatives etc. )through Javascript (Dr. Booleans adequate guide) and it was an eye-opener. Still no love for Haskell!

Typeclasses and parametric types are there to leverage the typesystem. It's hard to see how you can benefit from these abstractions if all you have is ducktyping.

Not a genuine answer, but JavaScript has a great ability to inspire respect for type systems, due to that duck typing.

I suppose the GP enforced it manually?

Javascript doesn't support duck typing. It doesn't support any typing actually: it's dynamically typed.

If Javascript can inspire respect for type systems, it's by making you realize that not having type annotations leads to terrible, unmaintainable code.

> Javascript doesn't support duck typing. It doesn't support any typing actually: it's dynamically typed.

Dynamically typed doesn't mean untyped; you still have types in JavaScript. Most dynamic languages are strongly typed, not untyped. You're conflating a few unrelated things. JavaScript is duck typed, as virtually all dynamic languages are.

Dynamic typing isn't lack of typing.

The fact that types cannot be statically checked doesn't mean you don't have any.

Bash only has one type, the string, and is thus statically typed.

Is Bash's type system better than say, Python's ?

Yes, that was my point.

Dynamic typing is a typing. Also, duck typing is used more in the dynamic sense than the static sense, where in the latter it is instead called structural typing.

Those abstractions are about static typing, not functional programming. Functional programming doesn't require static types.

dingdingding! we have a winner


At least you had documentation, books and a community to ask questions from. We had SML which had none of that. I wish we used Ocaml, that at least had something of an active community. Haskell would of been even better.

No, teach in Scheme; functional programming has shit to do with advanced static type systems.

No. The best language is likely the one you know best. Be that Ruby, JS, Rust, or C++.

That way you can concentrate learning the principles and you’ll immediately know how to apply them.

The basic principles aren’t hard anyhow - you can learn them completely in a day. The hard part is applying them and understanding the trade offs.


No. You need to understand monads before learning FP and you need to learn FP for understanding monads. This is chicken/egg problem. Functional programming is overrated.

> You need to understand monads before learning FP

No, you don't. You don't even need to understand them before learning Haskell, much less before learning FP using a language which doesn't use monads as pervasively as Haskell does.

You obviously need to learn at least something about monads as you learn Haskell, but understanding them is not a prerequisite.

I would lie if I said this isn't fun which is probably the reason why people do it in the first place even though their explanations might make it worse than just reading this:


Asking what a monad is is like asking what an iterator is. It doesn't tell you very much what it actually does because it depends on the implementation. The iterator is just an interface. A bunch of functions that have to be correctly implemented according to certain rules.

It all first started with lazyness. FP developers wanted a new modern language developed from the ground up. It should be a pure language. The haskell developers soon realised the evaluation order of a pure language must not necessarily be fixed. Eventually lazyness was born. Lazyness was a unique and very appealing feature for a purely functional programmming language. However as soon as a haskell program had to leave it's protective shell and interact with the real world lazyness turned into a double edged sword! FizzBuzzes were printing their buzzes and fizzes out of order! Chaos ensued and haskell developers returned back into the shell. After long years of work they have finally discovered it! A mechanism to force the evaluation order of a program to be partially sequential again! It is a new type of container that allows you to put another type inside it. However sometimes the only way to access the contained value is by giving the container a function that takes a the boxed value as input and returns another container with a boxed value inside! The value never escapes the box. And so was the (IO)monad born! You can now take two IO actions a and b and turn them into c which is a combination of a and b where the output of a is piped into b. Not only can we send messages to the outside world, we can also finally receive them!

Everyone was happy in haskell kingdom until the imperative migrants started writing monad tutorials... (including this one)

This story is fiction by the way.

As a bonus for all the wasted time. another crappy analogy: A cage inside a bird is given a machine that puts birds in cages. The regular tool called functor that only replaces what's inside the cage would give us a bird in a cage in a cage! The special tool gives us what we actually want! The tool named monad gives us a bird in a cage! No nested cages!

No, no more than you need to understand group theory before you learn to add and subtract or ring theory before you learn to multiply.

Better to teach how to use specific monads without using the dread m-word, and then say "You know, these all have something in common" and then talk about monads, or these days work your way up from Monoid to Functor to Applicative to Monad.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact