Skip to content

Instantly share code, notes, and snippets.

@afsalthaj
Last active June 10, 2018 23:02
Show Gist options
  • Save afsalthaj/ebbb4f0e3a038102f1379e79bdc09e40 to your computer and use it in GitHub Desktop.
Save afsalthaj/ebbb4f0e3a038102f1379e79bdc09e40 to your computer and use it in GitHub Desktop.

A few random thoughts on FP

Parametricity for the win!

Type parameterisation is done for us to later discover, for instance, that we could test our CRUD service layer with all combinations of errors a database can produce as a single test case. How many applications do that?...

Laws!

Any implementations should go with property based tests/laws. Else it is fairly hard to convince even ourselves why not a Java/Python/any imperative alternate. Let's don't be biased for no reason.

It is easier to convince that concurrency management and related library development with Scala (well, FP) is better as we love compositions than call backs and waiting. But application level FP usage is justified, for instance, when you are able to say “Let me push to master, coz it will work for sure”. That confidence comes easily with type driven development and laws.

Let's don't abuse abstraction design!

While abstraction of concrete implementations to a generic method is a valid pathway, let us also make sure we don't pollute our abstraction based on concrete implementations. It makes the code unreadable, complex and sometimes who knows...pointless.

In almost all situations, the design of our abstractions should be based on normal thinking with common sense, and not based on how bad the concrete implementations are

Example:

  • We discovered monoid is useful to add two immutable Maps, and we believe monoid was not designed specifically to this problem in the first instance.
  • Monoid abstracts the behaviour of associative append of two values and having a unit when appended doesn't change the result. The abstraction is clean and powerful enabling us to solve a variety of problems in the type class world!
  • In other words, Monoid is a perfect example of a clean abstraction not influenced by any specific solutions.
To a certain extent a "sense of solution to a usecase" allows you to abstract better

compared to you having a "complete understanding of the solution to a usecase".

So what is FP?

  • All of our functions should be total, side effect free (meaning, things that you are not sure about on how it works). Or in simpler terms, the function should work for all possible Inputs
  • The functions should be deterministic. Passing x should always return y. Even our system should be following this principle, and not just in isolated functions.
  • Mixing state management along with behaviours are not allowed. No one wants two threads of execution to mutate the state of an account balance, which is a public variable in a class that has debit and credit method in it. State and behaviours are to be always separated. This is achieved through algebraic data types, type classes and functions.
  • Believe in function passing, that may turn out to be your dependency injection. Believe in higher order functions. Pass the function A to the function B, instead of calling function A in function B.

Thats all FP is demanding us to do. Any usage of of Monad Transformers, Free Monads and advanced combinators are just secondary and it requires only learning. Usage of advanced constructs doesn't ever mean, our app is robust and testable.

If your app fails at any time with a bug, there are things to fix beyond "just patches". Obviously, there are no abstractions without a bit of leak and there are almost no abstractions which I know that can't be abused !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment