Good tutorial/book about functional programming?

Hi,
I want to learn more about functional programming in general. I watched some videos and read some tutorials, but I'm still struggling.

Can you recommend a video, tutorial or book that explains this paradigm from scratch in a simple and understandable way?

Regards
Markus

In my opinion, learning functional programming works best by learning a functional programming language. My personal favorite is Haskell, but there are of course others. Good learning resources for such a language will not just teach you its basic syntax etc, but also how to use it to build actual practical applications with it. I’m not entirely up to date with what modern (non-outdated) resources for learning Haskell are out there, but I’ve heard that haskellbook.com is pretty decent. (It is quite long and not for free, but it starts from the very basics.) There also is a list of other, free learning resources that the author of that book recommends, listed here.

4 Likes

I found a free crash course about functional programming in Rust. I haven't read it, but maybe it is helpful

4 Likes

Bear in mind that rust is not a functional language in the same sense that Haskell is.
Haskell forces you to code functional. You have no choice.
Languages like F# and oCaml encourage you to code functional. But you can choose to code imperative if you want to.
Rust is an imperative language. It has some functional features.

If you want to learn rust, it is a great language.
But if you want to learn what functional programming is all about, you should learn it in a functional language.

1 Like

I know that. That's why I also want to learn Elm. I know that Rust is a language with multiple paradigms, but I want to be able to write code that is as functional as possible.

Elm is a pleasure to write, in my experience.

I think a good place to start is Haskell, even if only for a learning experience. Once you can code in Haskell (even at a beginner level) then the functional mentality will have set in. You can then use some of these ideas in your other coding adventures, including in rust.

That could be a long road.

When I look at a Haskell program I don't see anything remotely recognizable as a programming language to get a grip on. Same trouble I have with Forth.

Is it really not possible to create a Functional Programming language with something in it that actually looks like it might be a function?

I have no use case for Haskell, but maybe for Elm as a front end for Rust programs.

So from my point it doesn't make sense to learn Haskell

Have you ever taken a look at this: http://learnyouahaskell.com/

It’s an entertaining read and the first chapter or two will make the Haskell code easier to read.

You don’t have to get as far as monads to appreciate why functional programming is so different to imperative programming, but if you do you will see why some people are pushing for HKT in rust.

1 Like

Thanks for the link. I do not know that yet.

What does "HKT" mean?

HKT is short for higher-kinded types, which means to have a generic parameter or associated type take on the value of Vec rather than Vec<u8> or Vec<String>. That said, the version typically talked about in Rust-land is about having lifetimes instead of u8 or String.

3 Likes

What does it mean for a generic parameter to take on the Value of 'Vec' ?
What on Earth would one do with such a thing?

I pretty much hate generics already, one can never be sure what one is looking at and the syntax is terrible.

HKT sounds far too meta for me.

The primary feature enabled by HKTs is to create streaming iterators (and streaming streams in async world), i.e. an iterator that produces values that may contain a reference into the iterator itself.

With the current Iterator trait, the following code must be valid no matter what the item type is:

let a = iter.next();
let b = iter.next();
println!("{:?}", a);

However imagine what would happen if a held a reference into iter. Then, since .next() mutates the iterator, the second call to next might invalidate the reference stored in a.

One feature you might imagine using this for would be an alternative to std::io::Lines. The Lines iterator currently allocates a new String every time you call .next(), but there's no reason you have to do that (and in fact you can avoid it with read_line instead). Such an alternate Lines iterator would have item type &str, with a String buffer stored inside the iterator, whose allocation is reused on every call to .next().

To see how this ties into HKTs, the technicality you need to understand is that &str is not a type because it's missing the lifetime. If you want a specific type, you need to say &'a str for some specific lifetime 'a, and given two different lifetimes 'a and 'b, there are two distinct types &'a str and &'b str. If we now take the example

let a = iter.next();
println!("{:?}", a);
let b = iter.next();
println!("{:?}", b);

then a and b have different lifetimes, and thus, despite both being a &str, have different types. With an ordinary iterator, every call to .next() must return the same type, but with HKTs for the item type, you are allowed to vary the generic lifetime parameter from call to call.

7 Likes

Consider me mind blown. I have no clue what you are saying. I might have to study that for some time to make any sense of it.

My first impression from "...whose allocation is reused on every call to .next()" is that the call for the further abstraction of HKTs is then to overcome a problem caused by the lesser abstraction we have already.

What I mean is, we used to be able to read streams of lines, reusing a buffer space, in C or even assembler !

Well sure, it's a problem with the Iterator abstraction. We can easily do this particular thing without the abstraction. The reason this abstraction is useful to add to Rust is that it makes this possible:

trait MyTrait {
    async fn foo(&self) -> String;
}
error[E0706]: functions in traits cannot be declared `async`
 --> src/lib.rs:3:5
  |
3 |     async fn foo(&self) -> String;
  |     -----^^^^^^^^^^^^^^^^^^^^^^^^^
  |     |
  |     `async` because of this
  |
  = note: `async` trait functions are not currently supported
  = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait

Currently you have to use the async-trait crate, but it makes an allocation on every function call. However, this allocation can be avoided if we have HKT (plus another feature known as GAT).

2 Likes

Well that is an odd coincidence. Over the weekend I found myself wanting an async function in a trait. And I found the async-trait to do it with.

It does seem we need more abstractions to make things possible that the abstractions below don't allow.

I liken it to having to invent the abstractions of break/continue in loops, and switch/case and ultimately exceptions, all to get around the issues caused by the abstraction of structured programming banning the goto :slight_smile:

1 Like

There's a series of courses from Washington University on Coursera: Programming Languages - Part A and Part B focus solely on functional programming.

Part A uses Standard ML, but it's rather about laying foundations for functional programming. I realized there are surprising of similarities between Rust and SML. Indeed, Rust lists SML as one of its main influences:

SML, OCaml: algebraic data types, pattern matching, type inference, semicolon statement separation

Part B uses Racket, a dialect of Scheme. However, as mentioned earlier, the focus is on learning to think functionally rather than learning these specific languages. Rust's macro system is inspired by the hygienic macros of scheme, which is dealt in detail in the course.

Both courses are well crafted. In addition to the video lectures, there are plenty of programming exercises. Perhaps a little more intense than online tutorials, but definitely worth the time.

1 Like

I don't mean to be inflammatory, but what do people actually use these Functional Programming languages for?

I mean, is there any software I might find myself using from day to day written in Haskell or whatever?

As far as I can tell our operating systems, GUIs, compilers, dev tools are all written in C or C++. With of course Rust making inroads.

I don't recall ever installing anything on Debian that pulled in a dependency on Haskell, StandardML, OCaml etc.

I appreciate that it may well be beneficial to get a new perspective on programming through learning an FP language, if one can ever understand it, but as a practical matter what is to be gained?

Pandoc is written in haskell.

2 Likes

Xmonad is written in Haskell

2 Likes