All Projects → phenax → Algebraic Effects

phenax / Algebraic Effects

Licence: mit
Manage side-effects in your javascript application cleanly with algebraic effects

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects

Projects that are alternatives of or similar to Algebraic Effects

Effect
effect isolation in Python, to facilitate more purely functional code
Stars: ✭ 324 (+100%)
Mutual labels:  functional-programming, effects
Zio
ZIO — A type-safe, composable library for async and concurrent programming in Scala
Stars: ✭ 3,167 (+1854.94%)
Mutual labels:  functional-programming, effects
Tofu
Functional programming toolbox
Stars: ✭ 281 (+73.46%)
Mutual labels:  functional-programming, effects
Bow
🏹 Bow is a cross-platform library for Typed Functional Programming in Swift
Stars: ✭ 538 (+232.1%)
Mutual labels:  functional-programming, effects
Fx Ts
Computational environments and effects for TypeScript
Stars: ✭ 42 (-74.07%)
Mutual labels:  functional-programming, effects
Parapet
A purely functional library to build distributed and event-driven systems
Stars: ✭ 106 (-34.57%)
Mutual labels:  functional-programming, effects
Pfun
Functional, composable, asynchronous, type-safe Python.
Stars: ✭ 75 (-53.7%)
Mutual labels:  functional-programming, effects
Functionaljava
Functional programming in Java
Stars: ✭ 1,472 (+808.64%)
Mutual labels:  functional-programming, effects
Doobie
Functional JDBC layer for Scala.
Stars: ✭ 1,910 (+1079.01%)
Mutual labels:  functional-programming
Fs2
Compositional, streaming I/O library for Scala
Stars: ✭ 1,998 (+1133.33%)
Mutual labels:  functional-programming
Munus
Power of object-oriented programming with the elegance of functional programming in PHP.
Stars: ✭ 149 (-8.02%)
Mutual labels:  functional-programming
Cube Composer
A puzzle game inspired by functional programming
Stars: ✭ 1,845 (+1038.89%)
Mutual labels:  functional-programming
L1
L1: Tensor Studio — The playground for tensors
Stars: ✭ 154 (-4.94%)
Mutual labels:  functional-programming
Rangeless
c++ LINQ -like library of higher-order functions for data manipulation
Stars: ✭ 148 (-8.64%)
Mutual labels:  functional-programming
Category Theory For Dotnet Programmers
This repo contains all c++ / haskell samples from Bartosz Milewski's book (Category Theory for Programmers) converted to csharp and fsharp
Stars: ✭ 159 (-1.85%)
Mutual labels:  functional-programming
Typelang
🌳 A tiny language interpreter implemented purely in TypeScript's type-system
Stars: ✭ 149 (-8.02%)
Mutual labels:  functional-programming
Rambdax
Extended version of Rambda
Stars: ✭ 148 (-8.64%)
Mutual labels:  functional-programming
Metalang99
A functional language for C99 preprocessor metaprogramming
Stars: ✭ 152 (-6.17%)
Mutual labels:  functional-programming
Kotlindiscretemathtoolkit
Set of extensions for Kotlin that provides Discrete math functionalities
Stars: ✭ 158 (-2.47%)
Mutual labels:  functional-programming
Pyfunctional
Python library for creating data pipelines with chain functional programming
Stars: ✭ 1,943 (+1099.38%)
Mutual labels:  functional-programming

Algebraic Effects

Manage your effects in a pure and composible way using algebraic effects with multiple continuations. https://phenax.github.io/algebraic-effects

CircleCI npm bundle size (minified + gzip) Codecov

Donate using Liberapay Buy Me A Coffee donate button

Documentation

Install

To add the project to your project

yarn add @algebraic-effects/core

If you want effects like Exception, State, Random, etc.

yarn add @algebraic-effects/core @algebraic-effects/effects

Usage

Import it to your file

import { createEffect, func } from '@algebraic-effects/core';
import { sleep } from '@algebraic-effects/core/generic';

State effect counter example

import { State } from '@algebraic-effects/effects';
import { call, sleep } from '@algebraic-effects/core/generic';

const countdown = function*() {
  const count = yield State.get();

  if(count > 0) {
    yield State.set(count - 1); // Decrement count
    yield sleep(1000); // Add a delay of 1 second
    yield call(countdown); // Recursively call the program again.
  }
}

State.of(10)(countdown)
  .fork(() => {}, () => alert('HAPPY NEW YEAR!!!!'));

Creating your own effects

  • Declare your effects
import { createEffect, func } from '@algebraic-effects/core';

export const ConsoleEffect = createEffect('ConsoleEffect', {
  log: func(['...data']),
});

export const ApiEffect = createEffect('ApiEffect', {
  fetchUser: func(['userid'], 'user'),
  markUserAsViewed: func(['userid']),
});

func function allows you to document the operation signature.

  • Write your program
const fetchProfile = function*(uid) {
  const user = yield ApiEffect.fetchUser(uid);

  yield ConsoleEffect.log('>> Fetched user user', uid);

  if(user.isPublic) {
    yield ApiEffect.markUserAsViewed(user.id);
    yield ConsoleEffect.log('>> Marked', uid, 'as viewed');
    return user;
  }

  return { id: uid, name: user.name, isPrivate: true };
}
  • Implement effect operation behavior
const logger = ConsoleEffect.handler({
  log: ({ resume }) => (...args) => {
    console.log(...args);
    resume();
  },
});

const api = ApiEffect.handler({
  markUserAsViewed: ({ resume, throwError }) =>
    uid => fetchJson(`/user/${uid}/mark-as-viewed`).then(resume).catch(throwError),
  fetchUser: ({ promise }) => uid => promise(fetchJson(`/user/${uid}`)),
});

promise is a shorthand for doing .then(resume).catch(throwError)

  • Calling your program
api.with(logger) // Compose your effect handlers together and run them
  .run(fetchProfile)
  .fork(
    e => { /* Handle error */ },
    user => { /* Handle success */ }
  )

Multiple continuations

You can call resume multiple times from your operation synchronously.

function flipCoins() {
  const isHead1 = yield Random.flipCoin(2);
  const isHead2 = yield Random.flipCoin(2);
  return [isHead1 ? 'H' : 'T', isHead2 ? 'H' : 'T'];
}

// // runMulti method will start your program in multiple continuations mode
Random.seed(10)
  .runMulti(flipCoins)
  .fork(identity, data => {
    console.log(data); // Probably [[H, T], [H, T], [T, H], [T, T]]
  });
Writing custom effect with multiple continuations
const ListEffect = createEffect('ListEffect', {
  takeItem: func(['list'], '*', { isMulti: true }), // isMulti flag indicates that this operation resumes multiple times
});

// Program will resolve with [3, 4, 6, 7]
function *program() {
  const item1 = yield ListEffect.takeItem([ 1, 4 ]);
  const item2 = yield ListEffect.takeItem([ 2, 3 ]);

  return item1 + item2;
}

const looper = ListEffect.handler({
  takeItem: ({ resume }) => list => list.forEach(resume),
});

// runMulti method will start your program in multiple continuations mode
looper.runMulti(program).fork(
  handleError,
  data => {
    console.log(data); // [3, 4, 6, 7]
  }
);

Contributing

License

Algebraic effects is under MIT licensed.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].