New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@matechs/effect

Package Overview
Dependencies
Maintainers
2
Versions
153
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@matechs/effect

Matechs Effect is a typescript library inspired by scala's ZIO and Haskell's RIO architecture.

  • 0.0.10
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
180
decreased by-59.37%
Maintainers
2
Weekly downloads
 
Created
Source

Introduction

Matechs Effect is a typescript library inspired by scala's ZIO and Haskell's RIO architecture.

It aims to provide a strong fundational block to build typescript code in a more testable and standardized way.

This library is composed at its core by the @matechs/effect package that exposes 2 effects

  • type Effect<R, E, A> = (r: R) => FutureInstance<E, A>
  • type ConcurrentEffect<R, E, A> = (r: R) => ConcurrentFutureInstance<E, A>;

The underlying FutureInstance/ConcurrentFutureInstance is provided by Fluture.

You can think of this type as a computation that requires an environment R to run.

An important point to note in the implementation is the src/overload.ts file where we extend and define the new abstract types required to specialize fp-ts behaviour to respect the variance of R & E.

The key difference is expressed in:

export interface Chain3E<F extends URIS3> extends Apply3<F> {
  readonly chain: <R, E, A, R2, E2, B>(
    fa: Kind3<F, R, E, A>,
    f: (a: A) => Kind3<F, R2, E2, B>
  ) => Kind3<F, R & R2, E | E2, B>;
}

export interface Monad3E<M extends URIS3> extends Applicative3<M>, Chain3E<M> {}

export interface PipeableChain3E<F extends URIS3> extends PipeableApply3E<F> {
  readonly chain: <R, E, A, B>(
    f: (a: A) => Kind3<F, R, E, B>
  ) => <R2, E2>(ma: Kind3<F, R2, E2, A>) => Kind3<F, R & R2, E | E2, B>;
  readonly chainFirst: <R, E, A, B>(
    f: (a: A) => Kind3<F, R, E, B>
  ) => <R2, E2>(ma: Kind3<F, R2, E2, A>) => Kind3<F, R & R2, E | E2, A>;
  readonly flatten: <R, E, R2, E2, A>(
    mma: Kind3<F, R, E, Kind3<F, R2, E2, A>>
  ) => Kind3<F, R & R2, E | E2, A>;
}

export interface PipeableApply3E<F extends URIS3> extends PipeableFunctor3<F> {
  readonly ap: <R, E, A, R2, E2>(
    fa: Kind3<F, R, E, A>
  ) => <B>(fab: Kind3<F, R2, E2, (a: A) => B>) => Kind3<F, R & R2, E | E2, B>;
  readonly apFirst: <R, E, B>(
    fb: Kind3<F, R, E, B>
  ) => <A, R2, E2>(fa: Kind3<F, R2, E2, A>) => Kind3<F, R & R2, E | E2, A>;
  readonly apSecond: <R, E, B>(
    fb: Kind3<F, R, E, B>
  ) => <A, R2, E2>(fa: Kind3<F, R2, E2, A>) => Kind3<F, R & R2, E | E2, B>;
}

export interface Apply3E<F extends URIS3> extends Functor3<F> {
  readonly ap: <R, E, A, B, R2, E2>(
    fab: Kind3<F, R, E, (a: A) => B>,
    fa: Kind3<F, R2, E2, A>
  ) => Kind3<F, R & R2, E | E2, B>;
}

In addition to that the fp-ts-contrib/lib/Do module has similar overloads. This workaround is necessary because typescript's lack of variance annotation on generics.

The module exposes 2 instances of the typeclass type EffectMonad<T extends URIS3> = Monad3E<T> & MonadThrow3<T> & Bifunctor3<T>:

  • effectMonad for Effect<R, E, A>
  • concurrentEffectMonad for ConcurrentEffect<R, E, A>

Pipeable functions are also exported for both instances (default Effect, parallel scoped under pipeablePar)

In addition to default implementations additional exposed functions are:

/* utils */
export function error(message: string) {
  return new Error(message);
}

/* lift functions */

export function fromFuture<E, A>(f: F.FutureInstance<E, A>): Effect<NoEnv, E, A>

export function right<A>(a: A): Effect<NoEnv, NoErr, A>

export function left<E>(e: E): Effect<NoEnv, E, never>

export function liftPromise<A, E>(f: () => Promise<A>): Effect<NoEnv, never, A>

export function liftIO<A>(f: () => A): Effect<NoEnv, never, A>

export function tryCatch<A, E>(f: () => Promise<A>, onLeft: (e: any) => E)

export function tryCatchIO<A, E>(f: () => A, onLeft: (e: any) => E)

export function chainLeft<R, E, E2, A, R2>(ma: Effect<R, E, A>,onLeft: (e: E) => Effect<R2, E2, A>)

/* conditionals */

// run only when predicate is true, return in Option
export function when(predicate: boolean): <R, E, A>(ma: Effect<R, E, A>) => Effect<R, E, Op.Option<A>>

// same as alt but types are different so we return in Either
export function or(predicate: boolean): <R, E, A>(ma: Effect<R, E, A>) => <R2, E2, B>(mb: Effect<R2, E2, B>) => Effect<R & R2, E | E2, Ei.Either<A, B>>

// decide what to run depending on a boolean, both side returns same type
export function alt(predicate: boolean): <R, E, A>(ma: Effect<R, E, A>) => (mb: Effect<R, E, A>) => Effect<R, E, A>

/* manipulate environment */

export const noEnv = {}; // unit

export function mergeEnv<A, B>(a: A): (b: B) => A & B // merge 2 environments

export const provide = <R>(r: R) => <R2, E, A>(ma: Effect<R2 & R, E, A>): Effect<R2, E, A> // provide environment to an effect


/* use environment */
export function accessM<R, R2, E, A>(f: (r: R) => Effect<R2, E, A>): Effect<R & R2, E, A>

export function access<R, A>(f: (r: R) => A): Effect<R, NoErr, A>


/* convert par/seq */
export function par<R, E, A>(ma: Effect<R, E, A>): ConcurrentEffect<R, E, A>

export function seq<R, E, A>(ma: ConcurrentEffect<R, E, A>): Effect<R, E, A>


/* parallel */

export function sequenceP<R, E, A>(n: number, ops: Array<Effect<R, E, A>>): Effect<R, E, Array<A>>


/* execution */

/* run an effect that requires no environment, return TaskEither */
function run<E, A>(ma: Effect<NoEnv, E, A>): () => Promise<Ei.Either<E, A>>

/* run an effect that requires no environment, return Promise(reject on error) */
promise<A>(ma: Effect<NoEnv, any, A>): Promise<A>

/* run an effect that requires no environment, return underlying Fluture fork */
fork<A, E>(res: (a: A) => void, rej: (e: E) => void): (ma: Effect<NoEnv, E, A>) => Cancel

An example of usage can be found in packages/tracing correspondent to @matechs/tracing and in its tests where an example implementation is used for testing.

Notes

This package is a work in progress syntax and functions might change, feedback are welcome and contributions even more!

Thanks

This library would have not been feasibly possible without the strong fundations of fp-ts and Fluture huge thanks to the Authors.

Another huge thanks goes to both the scala community (ZIO in specific) and the haskell community (RIO & Polysemy) from which inspiration is taken.

All of the above projects are advised!

FAQs

Package last updated on 18 Nov 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc