> I guess I still find FP very abstract as a concept. I'm starting to like the notion of immutability as a design goal.
I'm rather asking about OCaml or SML than about something abstract matters like denotational semantics, system-F or pure lambda calculus.
There are pretty much the same abstract concepts behind imperative programming languages as well: operational semantics, Turing machines, which, I argue, are even more complex.
And if you write OOP, you have to deal with open recursion, covariant/invariant/contravariant subtyping relations, late bindings, polymorphic self type etc etc. There is a book called ``Theory of objects'' by Luca Cardelli (who is guilty for both SML and C++, BTW) if you are interested.
You just don't bother yourself with this theory, and neither should you when programming FP. You don't bother number theory and arithmetic (complex topics) when doing simple addition in your code, right?
> But I'm very used to the POSIX interface and honestly programming against much else tends to get me out of my comfort zone a little too much
Then maybe your starting point should rather be this [1].
(Although this book is rather about system unix programming in OCaml than about language itself. For learning the language its manual should fit pretty well [2], finding a sweet spot between a narrated book and a standard. Other good and more in-depth introductions are [3] and [4]).
There is also a unikernel called mirage os which includes TCP stack and other stuff and gives a good taste of what system programming in OCaml looks like.
https://github.com/mirage
Edit:
> But then I'm the kind of sicko who enjoys assembly language to some degree, where practically every instruction has a side effect, whether it be assigning a value to a register, or setting a bit in a flag register, or doing I/O whether port mapped or memory mapped.
FP doesn't disallow side effects, a usual FP practices just encourage to deal with them explicitly. There are low-level FP languages like ATS [5] (though I discourage you to look at it since it's unnecessarily complicated and could demotivate you), F* [6][7] and even Coq to some degree [8] which allow to deal with effects like allocations and state just fine (and prove invariants).
[1] https://ocaml.github.io/ocamlunix/
[2] https://caml.inria.fr/pub/docs/manual-ocaml/
[3] http://dev.realworldocaml.org/
[4] http://ocaml-book.com/
[5] https://www.youtube.com/watch?v=zt0OQb1DBko
[6] https://fstarlang.github.io/lowstar/html/Introduction.html
[7] https://fstarlang.github.io/lowstar/html/LowStar.html#memory...
[8] https://www.microsoft.com/en-us/research/publication/coq-wor...