npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ts-bccc

v1.0.11

Published

TS-BCCC stands for "TypeScript Bi-Cartesian Closed Categories". TS-BCCC is a TypeScript library which implements a generic, expressive, and high performance series of universal combinators. These combinators can be used in many applications as a solid a

Downloads

298

Readme

Short introduction

TS-BCCC stands for "TypeScript Bi-Cartesian Closed Categories". TS-BCCC is a TypeScript library which implements a generic, expressive, and high performance series of universal combinators. These combinators can be used in many applications as a solid and reliable basis for building complex constructions such as monads, some of which are hierby included.

Getting started

Download the library with npm install ts-bccc or yarn add ts-bccc.

To start playing around with simple function pipelining, try the following:

import { Fun, fun, apply } from "ts-bccc";

let incr:Fun<number,number> = fun(x => x + 1)
let double:Fun<number,number> = fun(x => x * 2)
console.log(apply(incr.then(double.then(incr)), 3))

The sample builds a pipeline which first increments, then double, then increments again, and the pipeline is then invoked ("applied to") the number 3, leading us to an output of 9.

More complex data-types

We can build more complex datatypes such as tuples (products) and discriminated unions (sums). All datatypes can be mapped into datatypes with the same structure (products to products, sums to sums), or constructed/destroyed (value to product, sum to value).

The following example shows the mapping of a tuple:

import { Fun, fun, apply, Times } from "ts-bccc";

let incr:Fun<number,number> = fun(x => x + 1)
let double:Fun<number,number> = fun(x => x * 2)
let pair_transform:Fun<Times<number,number>, Times<number,number>> = incr.map_times(double)
console.log(apply(pair_transform, { fst:4, snd:2 }))

(4,2) is thus transformed into (5,4).

A product can be created from a single value and two functions which determine the values of the elements of the tuple:

let incr:Fun<number,number> = fun(x => x + 1)
let double:Fun<number,number> = fun(x => x * 2)
let mk_tuple:Fun<number, Times<number,number>> = incr.times(double)
console.log(apply(mk_tuple, 3))

3 is thus transformed into (4,6).

The dual operators are available for sums: map_plus and plus.

A library of equivalences

Given that the library implements Bi-Cartesian Closed Categories, there exist a series of equivalences which lead us to useful transformations between data types. The interesting bit of these transformations is that they mirror exactly a series of well-known equivalences from arithmetics. This makes these equivalences very easy to manipulate, as we do not need any effort to remember concepts such as a*(b+c) = a*b+a*c.

An equivalence such as a*(b+c) = a*b+a*c are reformulated as a series of built-in library functions such as:

distribute_sum_prod = function<a,b,c>() : Fun<Prod<a, Sum<b,c>>, Sum<Prod<a,b>, Prod<a,c>>> distribute_sum_prod_inv = function<a,b,c>() : Fun<Sum<Prod<a,b>, Prod<a,c>>, Prod<a, Sum<b,c>>>

An equivalence such as a^(b+c) = a^b * a^c is encoded as:

distribute_exp_sum = function<a,b,c>() : Fun<Fun<Plus<a,b>, c>, Prod<Fun<a,c>, Fun<b,c>>> ``distribute_exp_sum_inv = function<a,b,c>() : Fun<Prod<Fun<a,c>, Fun<b,c>>, Fun<Plus<a,b>, c>>`

Even simpler equivalences such as a+0 = a find their place, for example:

sum_identity = function<a>() : Fun<Sum<a,Zero>,a> sum_identity_inv = function<a>() : Fun<a,Sum<a,Zero>>

Examples of monads

Within the framework of Bi-Cartesian Closed Categories it is also possible to give a very elegant implementation of monads as monoids in the category of endofunctors. Monads are all (often articulated) endofunctors, but they can be built more easily as compositions of the generic types Plus, Times, and Fun, which themselves are (bi-)endofunctors as well.

For this reason, we can implement for example the State monad as State<S,A> = CCC.Fun<S, CCC.Prod<A,S>>, together with the required monadic operators:

st_map: function<B>(p:State<S,A>, f: CCC.Fun<A,B>) : State<S,B> st_join = function<S,A>(pp:State<S,State<S,A>>) : State<S,A> st_unit = function<S,A>(x:A) : State<S,A>

To be able to effectively use such a monad, we define a wrapper type which features more useful operators such as binding (then), thereby also mirroring standard library constructs such as Promise:

export interface St<S,A> extends CCC.Fun<S, CCC.Prod<A,S>> {}
export type State <S,A> = {
  run: St<S,A>,
  then: <B>(k: (_: A) => State <S,B>) => State <S,B>;
  ignore: () => State<S,CCC.Unit>;
  ignore_with: <B>(x:B) => State<S,B>;
  map: <B>(f: CCC.Fun<A,B>) => State <S,B>
}

It is noteworthy to realise that all of these operators are implemented fully and exclusively with the basic operators on products, sums, etc. which we have seen previously, leading us to a very homogeneous implementation overall. For example, notice how all of the following functions are no more than long BCCC pipelines:

export let st_run = function<s,a>() : Fun<State<s,a>, St<s,a>> { return fun(p => p.run) }

export let st_join = function<S,A>(pp:State<S,State<S,A>>) : State<S,A> {
  let g = fst<State<S,A>,S>().then(st_run<S,A>()).times(snd<State<S,A>,S>()).then(apply_pair())
  let h = st_run<S,State<S,A>>().map_times(id<S>()).then(apply_pair()).then(g)
  return mk_state<S,A>(apply(curry(h), pp))
}

export let st_get_state = function<S>() : State<S,S> { return mk_state<S,S>(id<S>().times(id<S>())) }
export let st_set_state = function<S>(s:S) : State<S,Unit> { return mk_state<S,Unit>(unit<S>().times(constant<S,S>(s))) }

export let st_unit = function<S,A>(x:A) : State<S,A> { return mk_state<S,A>(constant<S,A>(x).times(id<S>())) }

For an extensive example on using these monads in the practical implementation of a high performance meta-interpreter embedded in TypeScript, head over to ts-bccc-meta-interpreter.