β€’

newsletter

Effect systems: Functional Programming to the next level

Learn what is an Effect system and how Effect systems are the future of programming. Instead of using complex functional programming jargon, effect systems focus on solving real-world problems.


Sandro Maglione

Sandro Maglione

Software development

The future belongs to Effect systems.

Effect systems are used to provide compile-time check of the possible effects of the program

This week I worked on a prototype of an effect system in dart, aka fpdart v2 πŸ—οΈ

This is how it all looks like πŸ‘‡

Tweet not found

The embedded tweet could not be found…


Effect systems over functional programming

Functional programming is hard for 2 reasons:

  • Different paradigm from "usual" OOP
  • Jargon πŸ₯΄

Combine something different with mystic terms (e.g. Monad πŸ‘») makes people justified to run away

What we want instead:

  • Use both OOP and functional programming at their best
  • No Jargon, but solutions to real-world problems

Welcome to Effect systems πŸ’πŸΌβ€β™‚οΈ

Problems with fpdart (v1)

  • API surface: too many different classes, hard to understand what to use (Task, TaskEither, IO, Reader)
  • Interoperability: too many conversion functions (toTask, toTaskEither, toReaderTaskEither)
  • Jargon (from functional programming): things like Reader, Task, State
  • Not OOP friendly: classes like Eq are more useful in pure fp languages, less in dart

New Effect class

Solution: a single Effect class to handle all effects (dependencies, errors, success).

  • Remove all other classes (Task, IO, Reader and all)
  • No need of conversion function (everything is Effect)
  • No more jargon: removed methods like pure in favor of clear terms like succeed
  • Embrace dart OOP features

Furthermore, this allows to have a single Do notation function that handles all, Option and Either included.

There is more 🀩

Timeless coding principles, practices, and tools that make a difference, regardless of your language or framework, delivered in your inbox every week.

How this works

A single interface and a single Effect class:

abstract interface class IEffect<E, L, R> {
  final UnsafeRun<E, L, R> _unsafeRun;
  const IEffect._(this._unsafeRun);

  Future<Exit<L, R>> _runEffect(E env) async => _unsafeRun(env);

  /// ...
}

final class Effect<E, L, R> extends IEffect<E, L, R> {
  /// ...
}

This substitutes all other classes:

  • ReaderTaskEither: Effect<E, L, R>
  • TaskEither: Effect<dynamic, L, R>
  • Task (same as IO): Effect<dynamic, dynamic, R>

There is no distinction between sync and async code in the API.

This is achieved by using FutureOr:

typedef UnsafeRun<E, L, R> = FutureOr<Exit<L, R>> Function(E env);

In practice the usage is the same:

/// Create an [Effect] (same as [TaskEither])
final effect = Effect.tryCatch(
  () => Future.value(10),
  (error, stackTrace) => "Error",
);

/// Use the Do notation for all [Effect], [Option], [Either]
final doing = doEffect<int, String, int>(
  (_) async {
    final env = await _(Effect.ask());

    /// Use `withEnv` to provide a valid dependency value
    final mapped = await _(effect.map((r) => r + 10).withEnv(identity));

    /// Same for [Either] and [Option]
    final eitherValue = await _(Right<String, int>(10).withEnv<int>());
    final optionValue = await _(Some<int>(10).withEnv(() => "Some"));

    return mapped + eitherValue + optionValue;
  },
);

So, when?

This is still in the experimentation phase (not even alpha πŸ’πŸΌβ€β™‚οΈ). You can view and follow the progress on Github:

fpdart v2

This would be a radical change for fpdart: the most breaking change ever πŸ˜…

If this works I am going to open a discussion with the community to discuss how and if to move in this direction for fpdart v2

Stay tuned πŸ”œ


If you want a peek in how powerful effect system are take a look at Effect (typescript).

My goal is to provide something similar also in dart, but all adapted to the dart language and its features πŸ”₯

Working on it πŸ—οΈ

See you next πŸ‘‹

Start here.

Timeless coding principles, practices, and tools that make a difference, regardless of your language or framework, delivered in your inbox every week.