Notes from Professor Frisby's Mostly Adequate Guide to Functional Programming
Place for my notes from reading book: Professor Frisby's Mostly Adequate Guide to Functional Programming
Chapter 2: First Class Functions #
First part of this chapter is about remembring that functions can be assigned to variables.
Second is about seeing where there is no need for additional function. Example with ajaxCall
makes it obvious.
Example with controller calling views and having all those functions for no reason is great as well.
Argument with generic code is great, the same function can be reused if it's name is generic eg. compact
but not if it's called validArticles
.
Great argument for thisless, I have lost interest in it as well. Still think about this in context of other libraries.
Chapter 3: Pure Happines with Pure Functions #
Array slice - is pure - always returns the same thing.
Array splice is inpure - it mutates the array.
Use slice.
Using closures is impure - variables outside of the function can change and as the result function is impure.
"reliance upon state is one of the largest contributors to system complexity".
Ok, so to create purity use Object.freeze({prop: 21})
.
Side effects may include... #
"Water alone is not an inherent larvae incubator, it's the stagnant part that yields the swarms, and I assure you, side effects are a similar breeding ground in your own programs."
8th grade math #
Function is a relation between two values: the input and the output.
The case for purity #
- memoization - cacheable
"Something to note is that you can transform some inpure functions into pure ones by delaying evaluation"
- Portable / Self-Documenting
"The problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorrilla holding the banana... and the entire jungle"
— Joe Armstrong
- Testable
- Reasonable
- Parallel Code
Chapter 4: Currying #
var curry = require('lodash/curry')
"Giving a function fewer arguments that it expects is typically called partial application"
For some reason exercises are cryptic and I have no idea what I'm expected to do. Skipping.
Chapter 5: Coding by Composing #
var compose = function (f, g) {
return function (x) {
return f(g(x));
};
};
// associativity
var associate = compose(f, compose(g, h)) == compose(compose(f, g), h);
// true
Pointfree #
Debugging #
var trace = curry(function(tag, x) {
console.log(tag, x);
return x;
};
Category theory #
Category: collection with the following components:
- A collection of Objects
- A collection of morphisms (??)
- A notion of composition of the morphisms
- A distinguished morphism called identity
A collection of Objects - Data Types: #
String
, Boolean
etc. Sets of all possible values [true, false]
.
Morphisms == Pure Function #
A notion of composition of the morphisms #
compose
- just composition of functions
A distinguished morphism called identity #
var id = function (x) {
return x;
};
// identity
(compose(id, f) == compose(f, id)) == f;
// true
Chapter 6: Example application #
Declarative coding #
Application to get images from flickr written with functions - code is highly declarative.
var images = _.compose(_.map(_.compose(img, mediaUrl)), _.prop("items"));
Chapter 7: Hindley-Milner and Me #
// capitalize :: String -> String
var capitalize = function (s) {
return toUpperCase(head(s)) + toLowerCase(tails(s));
};
functions: a -> b
a function from 'String' to 'String', or from 'a' to 'b'
It looks like Haskell if we use curry:
// join :: String -> [String] -> String
var join = curry((what, xs) => xs.join(what));
We can use variables in types as in code, eg. 'a'
// id :: a -> a
var id = (x) => x;
// map :: (a -> b) -> [a] -> [b]
var map = curry((f, xs) => xs.map(f));
Narrowing the possibility #
Parametricity - the function will act on all types in a uniform manner
Chapter 8: Tupperware #
var Container = function (x) {
this.__value = x;
};
Container.of = function (x) {
return new Container(x);
};
Container.of(3);
Container.of("something");
// (a -> b) -> Container a -> Container b
Container.prototype.map = function (f) {
return Container.of(f(this.__value));
};
Container.of(2).map(function (two) {
return two + 2;
});
//=> Container(4)
It is Functor #
A Functor is a type that implements map
and obeys some laws
Functor == Mappable
Chapter 9: Monadic Onions #
A pointed functor is a functor with an of
method.
Monads are pointed functors that can flatten (have join
method)
My chain hits my chest #
// chain :: Monad m => (a -> m b) -> m a -> m b
var chain = curry(function (f, m) {
return m.map(f).join(); // or compose(join, map(f))(m)
});
chain is >>=
(pronounced bind or flatMap)
Because chain effortlessly nests effects, we can capture both sequence and variable assignment in a purely functional way.
Want to learn more?
Sign up to get a digest of my articles and interesting links via email every month.