Good read. He annotates his function with Hindley-Milner type signatures (specified in comments). I really prefer this to, say, jsdoc. Anyone know if there's a jsdoc-like tool that understands these comments? That'd be pretty swank.
I'm not sure what "Hindley-Milner type signatures" means. Obviously it is intended to refer to Haskell-style type signatures. Hindley-Milner, though, usually refers to a system of type inference which is independent of syntax.
As I understand it, the author is using Hindley-Milner as if was the name of a syntax, like Backus-Naur form. But this is something I've never heard, and I wonder if the credit for the Haskell type signature style belongs just as much to Rod Burstall or David Turner, in other words I'm inclined to believe that it is something conventional that evolved over years.
The Fantasy Land spec and related libraries like Sanctuary and Fluture deserve a mention here, even if only as a next step after reading this guide.
It helps bridge the gap between looking at all of this from the more math/Haskell perspective and how it's implemented in javascript, without sacrificing definitions (as much as possible).
Really enjoyed this book. Once you get currying, and using curried functions to pipe/compose, everything clicks into place. I found the examples of using Nothing/Maybe monads for error handling pretty neat as well - is that a common pattern, because I don't remember native support for those types when I briefly dabbled in elixir.
Also is his explanation of monads as 'functors that can flatten' a simplification for the purposes of teaching, or is that more or less what they are?
There's really multiple definitions of "functional" right now, and the type of "functional" being discussed here, Erlang isn't, and I don't think Elixir particularly is either.
This is not a criticism of any kind; this is a point about definitions. There are definitions of functional where Erlang is functional, and IIRC Elixir can be said to support it.
(And there are definitions of "functional" where almost every language in current use is "functional". There's even some so weak that C is "functional" because it has "function pointers", though this one is now out-of-date and not currently being used by anyone. But, yes, there was once a time in which C would have been considered "unusually strong" in its "functional programming" support, because other contemporary languages didn't even have function pointers.)
"Also is his explanation of monads as 'functors that can flatten' a simplification for the purposes of teaching, or is that more or less what they are?"
A little of both. Technically it is correct, but the "flattening" in question applies to many things that most programmers wouldn't consider "flattening". For instance, consider monadic IO as Haskell uses. There is a way in which you can consider the execution of an IO value as "flattening" it, and it corresponds to the mathematical term, but it's not what most people have in mind. There's more to "flattening" than "simplifying data structures in some manner"; it doesn't even always involve what we'd traditionally think of as data structures at all, such as, again, IO.
Personally I think it is an actively unhelpful metaphor for these reasons, as it is very prone to leading to false understanding, but YMMV.
Haskell-style types aren't a prerequisite for functional programming. Lisp and Elixir are dynamically-typed, which is why you don't see monads in those.
That said, they do occasionally form useful abstractions.
Functors have fmap. Pointeds have pure. Monads have fmap, pure and join/flatten. So what's missing from "functors that can flatten" is pure, and monads are more precisely "pointed functors that can flatten".
In my understanding however, it's valuable to note that the chain-ability of the bind operation also sets up a continuously nested set of closures, which is where the real power comes into play to give you a useful approximation to imperative programming. (This can easily be abused, of course, to circumvent thinking and structuring code functionally.)
Related to this, SJP stressed in a talk some years back about how monads conveniently encapsulate the unavoidable messiness of side-effects in the least painful way yet discovered.
The Option/Maybe monad is very common in FP languages. I don't know if it's native in Elixir, but apparently it's pretty easy to implement: http://www.zohaib.me/monads-in-elixir-2/#maybe
There are lots of ways to conceptualize monads. I think "functors that flatten" is accurate, but is just one way.
imo, that's basically what they are. altho the fact that they can be created via unit is actually really useful too (even tho thats technically part of applicative).
This is excellent. But man, I don't think I can ever go back to not feeling like there's a huge pedagogical gap between the local maxima the functional programming explanations engineers are typically exposed to, and the much higher (though probably still not a global maxima) point that pure mathematicians have been adapted into. I just wish we'd embrace the geometric (topological, differential geometrical) threads that a lot of these concepts (like lifts etc) are connected to, instead of being arbitrarily tied to a pedagogy textured by the sociological context that coding originated from (i.e. heavily influenced by logicians etc).
You should see the videos he made for Egghead.io! Stop motion hedgehog! I know some people complained, but Egghead backed his unconventional teaching methods which is pretty cool.
Robert Harper's 'Programming in Standard ML' free pdf off his CMU page is the best intro I've found to really understand FP, goes into details and reasons, like the pattern matching material. Very concisely written and SML is like Scheme, easy to learn syntax perfect for teaching.
When I started looking into Functional Programming, Professor Frisby's book was instrumental in my learning the concepts and applying them to a language I already know & code in.
Great book, really enjoyed. For people who wanna learn more about Functional Programming (Haskell,Purescript) from 101 to building product, I recommend this resources:
Why does he factor out the zero valued flock of birds variable?
That seems extremely dishonest. The reason why we name variables, is so that they can hold different values. There is no guarantee that every run of the script will have the same initial variables. If it was, you might as well just type in the result.
I wish I knew enough compsci to know why functional programming is useful. I read about half the book, and while interesting from a learning perspective I don't know where I can apply it.
Context: self-taught programmer in the data science/statistical modeling world.
Since I've started applying FP (I'm not very strict about it) I've been finding ways to reuse code more which lets me reduce my test footprint and increase the reliability of my code. I've also found it's easier to isolate my business logic without scoping it too strictly to an object or implementation, allowing me to think largely in coding to interfaces or contacts. This is totally doable with strict OO, but honestly I'm pretty lousy at that in practice. So FP has helped me with that too.
I lean towards organizing my applications into very dumb objects which are supported by FP-style business logic. At a glance you can infer what's going on quite easily due to the idiomatic use of the objects, but the object orientation mostly ends there. My business logic is organized into isolated modules that are as pure as I can manage without being a nut about it. The objects recruit or are operated on by that logic, so their implementation is very light and clean as a result. Like I mentioned, tests for this kind of code are really nice. They tend to be concise.
It's not perfect, but I feel like it's a way FP has greatly improved my code and what I deliver to my team in general. It's an attempt to merge the benefits of two paradigms, I suppose.
A pure function is more of a declaration of truth than a list of steps. When your whole application is made up of declarations of truth, it is simpler to reason about and rearrange.
It's simply the fact that the function depends on nothing but its inputs (but includes all the surprising ramifications of that).
Since the FP crowd is here, why is loading a program into memory, writing a register, or calling a function not seen as a side effect, but writing to disk is seen as a side effect? Or have I got it wrong?
I'm not really part of the FP crowd, but I'll take a stab at it. Note well, however, that what I say here could well be wrong.
On one level, there is no such thing as FP. All there is, is assembly-language (or binary) instructions being executed in a CPU that has access to some memory. (Almost) every instruction creates some kind of side effect (including changing the flags).
But nobody wants to program at that level, so we build abstractions on top of it. All higher-level languages create an abstraction. Even C creates an abstract machine, even though it's very close to the hardware. If the abstraction doesn't leak, you can just think about the abstraction, and ignore what's going on at the level(s) below it.
FP creates an abstraction that's at a higher level than many other abstractions. Within that abstraction, (almost) all you have are functions and values. Memory and registers are below that level. The changes to the call stack when you call a function are below that level. Those things are therefore not seen as side effects, because they are below the level of abstraction you're working at.
But disk is not. Therefore writing to disk is seen as a side effect, and those other things are not.
Loading a program into memory is part of runtime(it happens before your program starts executing; so how is that useful to model that?); Why would calling a function be a side-effect?
Not sure what exactly you mean by writing a register; if you directly mutate a location, it is considered side-effect. Otherwise any register rewrites that happen are just implementation details and if you have a different architecture than von-neumann than it could also be implemented without writing to a register.
As long as software is executed in the real world you have side effects, including "side effects" coming in from the outside, like bits flipped in RAM. Yes. So let's just be practical. We can have the equivalent of a middle ages theological discussion or one rooted in this world :-)
Functional programming (FP) is an important paradigm with many practical benefits, such as preventing bugs, improving parallelization, etc.
JavaScript is a language in which one can apply the FP paradigm, with some (considerable) effort. This book explains both the underlying FP paradigm and how to apply it in JS.
Other languages (e.g. Haskell, Scala, F#) are designed for the FP paradigm and make it much easier to apply. But the paradigm itself is the same for all of them, as it arises from fundamental mathematical laws.
Actually the course on Egghead is terrible. The voice that is used to comment on the video is very badly recorded and I have no idea why they chose that voice for a serious video for adults.
Edit: Also fine to not have my opinion on this, but a lot of people shared my opinion, check the Egghead comment section. I would've loved to watch that video, with a more professional voice and walkthrough.
What's with this modern internet culture of calling everything "terrible" or "garbage" because it has some defects, even subjective ones?
I've watched this gradual change in the users of my own forum I started over 10 years ago. People with no skin in the game think so highly of their opinion that they use it to discredit and dismiss something as terrible garbage.
Seems related to the rise of self-entitlement culture: In this case, a free video series is terrible because you didn't like the voice.
I _love_ the videos on the Professor Frisbee Egghead course.
I learned a lot from the course content and the classroom stop-motion animations were refreshing; it kept me watching with a smile on my face.
It's nice to have some personality and silliness in an online classroom environment; very little differentiates the various JS teaching sites other than their media players and subject matter coverage right now.
Daniel Shiffman's unique style also breaks the “person tonelessly narrating to occasional cursor movements over a screencap” standard that lots of online courses have settled into, and is similarly engaging as a result: https://www.youtube.com/channel/UCvjgXvBlbQiydffZU7m1_aw
I completely understand that it could be more difficult for non-native speakers to understand. It's been sped up to match the cartoon style characters that he uses, and presumably for information density. I personally really enjoyed it, even if I did have to frequently pause the videos to recap something he had just said.
The course on Egghead is universally excellent and beyond reproach, any suggestion otherwise can be dismissed with prejudice.
May I suggest a perspective modification? I believe you can start your journey to recovery with a healthy doze of this https://www.youtube.com/watch?v=hUes6y2b--0, more of the same, twice a day, complete the course, or until the pressure in your loins subside.
> We have all the features we need to mimic a language like Scala or Haskell with the help of a tiny library or two.
Seems misleading at best, as you mimic only some parts of functional programming. For example, for-loops are not used but neither are recursion and tail calls mentioned.
> [T]yped functional languages will, without a doubt, be the best place to code in the style presented by this book. JavaScript will be our means of learning a paradigm, where you apply it is up to you.
Surprising how they teach the typed functional programming paradigm in a language which does not support you in it. Going from JavaScript to Haskell, wouldn't PureScript be a better stepping stone than this? Consider tail call elimination or all the support that type checking gives you to get the type nestings right, especially when you are a beginner and may have issues even with String being [Char] (unlike JavaScript) let alone Monads etc.
(EDIT: In case you didn't check the contents of the book: Yes, this is a book that teaches Monads, type classes, pointfree style, Hindley-Milner(!) etc., not a form of FP that would be natural in JS.)
It seems like a good book, but I think this is fair criticism. It skips some of the basic FP concepts that you mentioned, and is surprisingly heavy on more advanced topics (e.g. category theory, which I personally enjoy).
Most of the book isn't really a beginner's guide. A more accurate title might be "JavaScript for Haskell Programmers".
Most people are familiar with JS, not a lot of people have experience with Haskell or OCaml, or F# (Otherwise, they wouldn't really find any of this useful.)
And to the point... how would one go about taking "Imperative Haskell" Code and making it more functional... you can't. Either you write Haskell functionally or whatever you wrote will refuse to compile. I love this book and the Egghead.io videos that followed. I love this guide and the egghead.io videos. That content made me curious about Haskell and Tacit Programming.
jwarren|7 years ago
zupa-hu|7 years ago
(Skip to 0:30 in the first video, it's full of this kind of "context".)
AlexCoventry|7 years ago
How do you transform someone's voice like that?
lolive|7 years ago
vga805|7 years ago
Kyle wrote the You Don't Know JS series. This book is just as good.
christophilus|7 years ago
theoh|7 years ago
As I understand it, the author is using Hindley-Milner as if was the name of a syntax, like Backus-Naur form. But this is something I've never heard, and I wonder if the credit for the Haskell type signature style belongs just as much to Rod Burstall or David Turner, in other words I'm inclined to believe that it is something conventional that evolved over years.
RobertKerans|7 years ago
dakom|7 years ago
It helps bridge the gap between looking at all of this from the more math/Haskell perspective and how it's implemented in javascript, without sacrificing definitions (as much as possible).
blindwatchmaker|7 years ago
Also is his explanation of monads as 'functors that can flatten' a simplification for the purposes of teaching, or is that more or less what they are?
jerf|7 years ago
This is not a criticism of any kind; this is a point about definitions. There are definitions of functional where Erlang is functional, and IIRC Elixir can be said to support it.
(And there are definitions of "functional" where almost every language in current use is "functional". There's even some so weak that C is "functional" because it has "function pointers", though this one is now out-of-date and not currently being used by anyone. But, yes, there was once a time in which C would have been considered "unusually strong" in its "functional programming" support, because other contemporary languages didn't even have function pointers.)
"Also is his explanation of monads as 'functors that can flatten' a simplification for the purposes of teaching, or is that more or less what they are?"
A little of both. Technically it is correct, but the "flattening" in question applies to many things that most programmers wouldn't consider "flattening". For instance, consider monadic IO as Haskell uses. There is a way in which you can consider the execution of an IO value as "flattening" it, and it corresponds to the mathematical term, but it's not what most people have in mind. There's more to "flattening" than "simplifying data structures in some manner"; it doesn't even always involve what we'd traditionally think of as data structures at all, such as, again, IO.
Personally I think it is an actively unhelpful metaphor for these reasons, as it is very prone to leading to false understanding, but YMMV.
yen223|7 years ago
That said, they do occasionally form useful abstractions.
tuukkah|7 years ago
This is the canonical source: https://wiki.haskell.org/Typeclassopedia
lr4444lr|7 years ago
In my understanding however, it's valuable to note that the chain-ability of the bind operation also sets up a continuously nested set of closures, which is where the real power comes into play to give you a useful approximation to imperative programming. (This can easily be abused, of course, to circumvent thinking and structuring code functionally.)
Related to this, SJP stressed in a talk some years back about how monads conveniently encapsulate the unavoidable messiness of side-effects in the least painful way yet discovered.
brianberns|7 years ago
There are lots of ways to conceptualize monads. I think "functors that flatten" is accurate, but is just one way.
green_on_black|7 years ago
gcanti|7 years ago
picardo|7 years ago
tomduncalf|7 years ago
tw1010|7 years ago
uryga|7 years ago
AlexCoventry|7 years ago
projectileboy|7 years ago
lainga|7 years ago
stuntkite|7 years ago
- https://egghead.io/instructors/brian-lonsdorf
- https://www.youtube.com/watch?v=h_tkIpwbsxY
I'm pretty sure he's the only person to make this topic so approachable. I'm glad he's into having fun with it. Quite refreshing!
hackermailman|7 years ago
csixty4|7 years ago
allenleee|7 years ago
FP Resources:https://github.com/functionalflow/brains/projects/9
ericyang321|7 years ago
wodenokoto|7 years ago
That seems extremely dishonest. The reason why we name variables, is so that they can hold different values. There is no guarantee that every run of the script will have the same initial variables. If it was, you might as well just type in the result.
tomrod|7 years ago
Context: self-taught programmer in the data science/statistical modeling world.
steve_adams_86|7 years ago
I lean towards organizing my applications into very dumb objects which are supported by FP-style business logic. At a glance you can infer what's going on quite easily due to the idiomatic use of the objects, but the object orientation mostly ends there. My business logic is organized into isolated modules that are as pure as I can manage without being a nut about it. The objects recruit or are operated on by that logic, so their implementation is very light and clean as a result. Like I mentioned, tests for this kind of code are really nice. They tend to be concise.
It's not perfect, but I feel like it's a way FP has greatly improved my code and what I deliver to my team in general. It's an attempt to merge the benefits of two paradigms, I suppose.
charlieflowers|7 years ago
A pure function is more of a declaration of truth than a list of steps. When your whole application is made up of declarations of truth, it is simpler to reason about and rearrange.
It's simply the fact that the function depends on nothing but its inputs (but includes all the surprising ramifications of that).
dagurp|7 years ago
0xdeadbeefbabe|7 years ago
AnimalMuppet|7 years ago
On one level, there is no such thing as FP. All there is, is assembly-language (or binary) instructions being executed in a CPU that has access to some memory. (Almost) every instruction creates some kind of side effect (including changing the flags).
But nobody wants to program at that level, so we build abstractions on top of it. All higher-level languages create an abstraction. Even C creates an abstract machine, even though it's very close to the hardware. If the abstraction doesn't leak, you can just think about the abstraction, and ignore what's going on at the level(s) below it.
FP creates an abstraction that's at a higher level than many other abstractions. Within that abstraction, (almost) all you have are functions and values. Memory and registers are below that level. The changes to the call stack when you call a function are below that level. Those things are therefore not seen as side effects, because they are below the level of abstraction you're working at.
But disk is not. Therefore writing to disk is seen as a side effect, and those other things are not.
xfer|7 years ago
Not sure what exactly you mean by writing a register; if you directly mutate a location, it is considered side-effect. Otherwise any register rewrites that happen are just implementation details and if you have a different architecture than von-neumann than it could also be implemented without writing to a register.
sbov|7 years ago
Calling these side affects is like calling Python a low level language because programs you write still use registers and raw memory access.
ItsMe000001|7 years ago
halis|7 years ago
ponitozhekoni|7 years ago
mkirklions|7 years ago
Can anyone explain?
brianberns|7 years ago
JavaScript is a language in which one can apply the FP paradigm, with some (considerable) effort. This book explains both the underlying FP paradigm and how to apply it in JS.
Other languages (e.g. Haskell, Scala, F#) are designed for the FP paradigm and make it much easier to apply. But the paradigm itself is the same for all of them, as it arises from fundamental mathematical laws.
akuji1993|7 years ago
Edit: Also fine to not have my opinion on this, but a lot of people shared my opinion, check the Egghead comment section. I would've loved to watch that video, with a more professional voice and walkthrough.
sctb|7 years ago
always_good|7 years ago
I've watched this gradual change in the users of my own forum I started over 10 years ago. People with no skin in the game think so highly of their opinion that they use it to discredit and dismiss something as terrible garbage.
Seems related to the rise of self-entitlement culture: In this case, a free video series is terrible because you didn't like the voice.
modernerd|7 years ago
I learned a lot from the course content and the classroom stop-motion animations were refreshing; it kept me watching with a smile on my face.
It's nice to have some personality and silliness in an online classroom environment; very little differentiates the various JS teaching sites other than their media players and subject matter coverage right now.
Daniel Shiffman's unique style also breaks the “person tonelessly narrating to occasional cursor movements over a screencap” standard that lots of online courses have settled into, and is similarly engaging as a result: https://www.youtube.com/channel/UCvjgXvBlbQiydffZU7m1_aw
teebot|7 years ago
jwarren|7 years ago
aarpmcgee|7 years ago
ageofwant|7 years ago
May I suggest a perspective modification? I believe you can start your journey to recovery with a healthy doze of this https://www.youtube.com/watch?v=hUes6y2b--0, more of the same, twice a day, complete the course, or until the pressure in your loins subside.
tuukkah|7 years ago
Seems misleading at best, as you mimic only some parts of functional programming. For example, for-loops are not used but neither are recursion and tail calls mentioned.
> [T]yped functional languages will, without a doubt, be the best place to code in the style presented by this book. JavaScript will be our means of learning a paradigm, where you apply it is up to you.
Surprising how they teach the typed functional programming paradigm in a language which does not support you in it. Going from JavaScript to Haskell, wouldn't PureScript be a better stepping stone than this? Consider tail call elimination or all the support that type checking gives you to get the type nestings right, especially when you are a beginner and may have issues even with String being [Char] (unlike JavaScript) let alone Monads etc.
(EDIT: In case you didn't check the contents of the book: Yes, this is a book that teaches Monads, type classes, pointfree style, Hindley-Milner(!) etc., not a form of FP that would be natural in JS.)
brianberns|7 years ago
Most of the book isn't really a beginner's guide. A more accurate title might be "JavaScript for Haskell Programmers".
weatherlight|7 years ago
And to the point... how would one go about taking "Imperative Haskell" Code and making it more functional... you can't. Either you write Haskell functionally or whatever you wrote will refuse to compile. I love this book and the Egghead.io videos that followed. I love this guide and the egghead.io videos. That content made me curious about Haskell and Tacit Programming.