Skip to content

Instantly share code, notes, and snippets.

@mikearnaldi
Last active May 31, 2022 18:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikearnaldi/19957bfbd953ef6f9d1011f59bb2299a to your computer and use it in GitHub Desktop.
Save mikearnaldi/19957bfbd953ef6f9d1011f59bb2299a to your computer and use it in GitHub Desktop.

Reason for the gist

Apparently my account is somehow shadow-banned on reddit (no one's fault, never really used it).

The thread this reply was posted to is: https://www.reddit.com/r/typescript/comments/o2sn3p/which_is_the_best_functional_programming_library/h40l3iu/?utm_source=share&utm_medium=web2x&context=3

Reply

Disclaimer: I am the author of effect-ts.

Effect-ts has been developed from the experience of having both used fp-ts in production and having extended fp-ts to support patterns inspired by zio in Scala.

The first version of effect-ts, named matechs/effect, was based on fp-ts, with the evolution of the library we progressively diverged from fp-ts standards on a number of points that I will try to outline together with the key differences:

  • Modules are variant by default while in fp-ts invariance is the default (for example Either's chain allows for different error types)

  • Both pipeable & data-first functions exposed, fp-ts only exposes pipeable (for example in effect chain and chain_ are both exposed and chain_(fa, f) = pipe(fa, chain(f)).

  • Wide API exposed for every module and many concrete modules focused on day-to-day business needs, fp-ts focuses on providing abstractions with small integration with the native JS types and modules like for example Task is represented as a lazy native Promise. Effect-ts includes a full port of ZIO from Scala (1 to 1) with all its data types like Effect, Managed (managed resources like database connections, things that require opening & closing), Stream (streaming computations in constant memory), Fiber (effect is backed by a Fiber-based system, the same that ZIO uses, that supports supervision and fork-join identity), FiberRef (like a ThreadLocal), Queue (work-stealing concurrent queues, bounded, unbounded, sliding, etc), Ref (state references), RefM (synchronized state references), STM (software-transactional-memory, transactional data structures & synchronization primitives like Gates), Chunk (array-like with O(1) concat, append, prepend, etc), plus a set of modules like persistent collections (List, HashMap, HashSet, RBTree, etc) that bridge the language gap. Almost all (with very few exceptions) the modules are stack-safe via trampolining (that means Effect will never blow up the call stack).

  • Including a full port of ZIO means also that almost all the ecosystem libraries of ZIO can be ported to effect-ts, like for example @effect-ts/query that enables query optimizations with batching and pipelining (for example solved the N+1 problem)

  • Target of TypeScript, while effect-ts targets only the most recent TS version (at the moment 4.3+) fp-ts has in its objectives wider compatibility (this being a double-edged sword while being useful and good to support older language it does restrict the features used). This is important for all the next points.

  • Higher-Kinded Types in effect-ts supports transformers out of the box, for example, OptionT.monad(Either.monad) gives you a valid monad instance for Either<_, Option<_>> while in fp-ts you would need to index the composed type in one of the URItoKind type-level maps.

  • Higher-Kinded Types in effect-ts supports up to 10 type parameters and any number of fixed parameters.

  • Higher-Kinded Types in effect-ts supports explicit variance annotations (for example the chain of either has E variant) and constraints (for example you can fix not only E but any of the 10 available params).

  • Higher-Kinded Types in effect-ts do not require multiple overloads, each typeclass is a single definition (in fp-ts every typeclass requires multiple definitions Functor, Functor1, Functor2, Functor2C, Functor3, Functor3C, Functor4, Functor4C, etc.

  • Leverage compiler plugins to embed traces at compile-time that are used to provide granular cost-free execution tracing (when effect fails with a non handled error a full trace is rendered including fibers that forked the current process, where the process was supposed to continue and where the error is raised from).

  • Leverage compiler plugins to optimize code, for example, all the calls to pipe are removed and all the pipeable functions are rewritten in terms of data first (for example you write pipe(a, X.chian(f), X.chain(g)) becomes X.chain_(X.chain_(a, f), g)

  • Leverage compiler plugins to provide cost-free, extensible and tree-shakable fluent APIs, for example you write a.chian(f).chain(g) and the compiler transforms it to X.chain_(X.chain_(a, f), g) (an implication of this is that we can also extend native types like array to do things like [...elements].mapM(f) where if f returns Either you get Either<_, [...results]> or if f returns Option you get Option<_, [...results]>.


Overall to conclude effect-ts is a very big project in its early days, already used in production by a decent amount of companies but that still has its rough edges for example the lack of beginner-friendly documentation that we are planning to address during the next 1-2 years.

At the moment the development of effect-ts is sponsored by commercial projects that are using it intensively and progressively more and more by a growing community of supporters and contributors, join us using Discord: https://discord.gg/hdt7t7jpvn.

With my company, MATECHS https://www.matechs.com, we provide commercial support, and in partnership with Ziverge https://www.ziverge.com, we provide training workshops both to the public and to companies, our next public one will be in September https://www.eventbrite.co.uk/e/practical-functional-programming-with-typescript-london-edition-tickets-159683316097

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