Hacker News new | past | comments | ask | show | jobs | submit login

The intro page says this course is not about OCaml, but then the remaining pages go into detail about the various features of OCaml. The problem with this approach is that when you read about a feature, you don't know if it is a OCaml-specific thing or whether it is a general functional programming concept.

I would like to see a course or textbook that explains functional programming in the abstract. Instead of going into the details of any one functional language, gives examples of how various functional languages implement the various core ideas of functional programming.

So, explain functional programming concepts such as pure functions, referential transparency, functors, monoids, monads, effects, lazy evaluation and so on, not in the context of any specific language, but giving examples from multiple functional languages.

In other words, focus on functional programming in general, instead of one specific implementation of it. I have been looking for such a textbook or course, but it doesn't exist.




I don't think that would be helpful. If a book is too abstract it won't teach anything useful. Teaching something concrete is a good way to allow students to synthesize abstract ideas over time. And OCaml is a good vehicle for it because it has so much in common with other mainstream languages, especially nowadays with the trend towards functional/imperative/OOP mixed paradigms.


> If a book is too abstract it won't teach anything useful.

Lots of developers are curious about functional programming. Even if you don't program in a functional programming language, many principles of functional programming, such as pure functions, can be applied in any language. Almost all languages in use today, including JavaScript, C#, Java, Python and Rust have varying degrees of FP features. Understanding what FP is all about is helpful in learning those features.

I'd argue that the market for learning what FP is all about, and how you can apply FP features in traditional languages, is bigger than the market for learning specific FP languages such as OCaml, Scala, F# and so on.


But in order to teach something actually useful you need to provide code samples in a specific language. Speaking in generalities like 'Functional programming emphasizes pure functions' doesn't really tell people how to practice it.


Sure, and as I said before, provide examples in multiple languages, because the demographic I am talking about is interested in FP, not one particular FP language.


Overloading the learner with examples from multiple languages is also a bad teaching method. It just adds to the confusion and complexity. They will be overwhelmed with the different techniques needed to bolt functional programming on to various degrees in C#, JavaScript, Rust, etc.

When teaching, it's much better to teach as little as possible at a time, so that learners can absorb concepts easily through their working memory and then build on their knowledge over time.


Programs = Algorithms + Data Structures

Hence why I really favour CS books that rather pick a pseudo-code language, than trying to sell language X as part of exercises.


Not a book, but you may like it, i did:

https://www.lihaoyi.com/post/WhatsFunctionalProgrammingAllAb...

(edit) a post that uses JS, PHP, Python etc. to explain many FP concepts: http://chriswarbo.net/blog/2015-01-18-learning_functional_pr...


If you can find a copy, the first edition of ‘Introduction to Functional Programming’ by Richard Bird covers the concepts of functional programming in a language-agnostic way.


> functors, monoids, monads, lazy evaluation

These three things are mostly Haskell-specific though, at least in relation to functional programming.



Rust 'does' lazy evaluation only in the sense that you can implement it if you go out of your way. It's not the default like in Haskell. It's not a functional programming language–having functors, monoids, and monads (in some restricted sense) doesn't make a language FP.


Lazy evaluation is not a requirement of functional programming. There's nothing really in typed lambda calculus requiring any laziness, that's just one possible way of expression evaluation.

The only real requirement of functional programming is the support of first class functions, the possibility to pass and return functions like any other values.

If you want to discuss your own interpretation of what makes a language more or less functional, which could be interesting, please provide a definition first.


Note that I didn't say that lazy evaluation is needed for functional programming. I said that Rust doesn't have lazy evaluation, and that it's not a functional programming language.

IMHO, a functional programming language requires:

- First-class functions and function literal (lambda) syntax support

- Expression-oriented syntax

- Emphasis on immutable data structures

- Tail call optimization

Other features are 'take-it-or-leave-it'.


So given that ML languages don't require tail call optimizations, and allow for mutable data structures....


AFAIK all ML languages support tail call optimization, and put the emphasis on immutable data structures.


Nope, Scheme is one of the few languages that require tail call optimisation as per language standard.

There is no emphasis when mutability is one mut and ref cell away.


OCaml doesn't have a language standard afaik, and its implementation(s) support(s) TCO, so imho that's more important.

'Emphasis' just means the 'paved path', i.e. default data structures like records and variants are immutable, default list type is immutable. Of course if you want mutable stuff it's there, but it's not the default.


Even so, OCaml isn't all ML languages.


Afaik all ML languages have TCO, let me know if I'm wrong.


> The only real requirement of functional programming is the support of first class functions, the possibility to pass and return functions like any other values.

By that definition C language supports functional programming. I think a lot of people would disagree with your definition.


It does. I enjoyed the book Functional C by Hartel & Muller a lot:

https://www.semanticscholar.org/paper/Functional-C-Hartel-Mu...

It uses SML, had fun learning this stuff on the train with termux and vim.


Actually, first class functions also means the ability to form functions (ie, closures). Javascript for instance has that feature. I think that python also supports it. C OTOH doesn't, but it has other advantages.


Basic implementation for car, cdr, map with function pointers and clang blocks, the rest of Lispy stuff is left as an exercise. :)

https://godbolt.org/z/Y5qWs4c64


That's cool!

C++ had support for partial applications with templates (std::bind iirc), and it was possible to implement closures as objects with the () operator implemented. Now it has support for closure with a dedicated syntax.

It would be possible to do something similar in C - a closure is just a function pointer and a bunch of parameters bundled together, but I don't think there's enough flexibility in the language to make it look like regular function calls.


I don't think it's particularly out of the way. Iterators are a normal part of rust, and are lazy.


Rust doesn't have useful functors or monads since it doesn't have higher-kinded types.


Monads or something like them are vital to be able to recover imperative programming in a functional context. If functional programming means programming with functions (in the mathematical sense) then it means expression-oriented languages/styles, and how you express conventional (procedural) programming idioms in those is a key part of having a functional programming language that you can actually use.


What's wrong with OCaml's approach of just breaking out in imperative-style code whenever it suits you?


Imo, the advantage of "Haskell's approach" is that it's always obvious when you can and can't use imperative code, and the type system enforces it. I think this is important in many contexts, like STM[1] or Facebook's React[0]. But there are plenty of disadvantages:

* it's a bit more verbose.

* you can accidentally implement a weaker interface than the one you'd want, e.g. by only implementing Functor and not Traversable for your data structure.

* the flip side of the benefits is that adding I/O to a previously pure function changes its interface.

I don't know how it'd compare to OCaml's algebraic effects proposal, though.

[0]: https://reactjs.org/docs/hooks-effect.html

[1]: http://joeduffyblog.com/2010/01/03/a-brief-retrospective-on-...


You lose the freedom to fearlessly refactor that's the main advantage of functional programming. If it's not clear which parts of the code can be reordered then you either just can't keep the code clean anywhere near as much, or you need much higher test coverage etc. to keep the same level of confidence when you do.


There's nothing Haskell specific about those concepts. In fact, the first three where developed by mathematicians long before Haskell even existed.


When mathematicians developed monads, they were doing abstract algebra. They were not using them as a kludge to (for example) impose sequence on functional programming.

Having to use monads for sequencing is something that happens in Haskell and not in Rust.


Sure, I/O in Rust is a little easier because it's not wrapped up in an abstract type, but in exchange, Rust needs Try, async/.await and const-fn to solve just a few of the issues that monads solve in more generality. I don't think either choice is a kludge, it's just a bunch of trade-offs.


Just to say, Haskell doesn't need monads to sequence computations, in fact Haskell as a programming language (1989) is older than Moggi's seminal paper on monads applied to programming in 1993.


True, but imo Haskell I/O was less than pretty before monadic IO came along: https://stackoverflow.com/a/17004448




Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: