Coder Social home page Coder Social logo

funfix / funfix Goto Github PK

View Code? Open in Web Editor NEW
632.0 13.0 25.0 1.6 MB

Functional Programming Library for JavaScript, TypeScript and Flow ✨⚡️

Home Page: https://funfix.org

License: Apache License 2.0

JavaScript 3.85% TypeScript 96.10% Shell 0.05%
fp functional-programming javascript typescript flowtype es2015 type-classes async concurrency futures

funfix's Introduction

Funfix

Travis Coverage Status Greenkeeper badge npm Join chat

Funfix is a library of type classes and data types for Functional Programming in JavaScript, TypeScript and Flow.

Inspired by Scala, Cats and Monix.

Usage

The code is organized in sub-projects, for à la carte dependencies, but all types, classes and functions are exported by funfix, so to import everything:

npm install --save funfix

Or you can depend on individual sub-projects, see below.

Modules: UMD and ES 2015

The library has been compiled using UMD (Universal Module Definition), so it should work with CommonJS and AMD, for standalone usage in browsers or Node.js.

But it also provides a module definition in package.json, thus providing compatibility with ECMAScript 2015 modules, for usage when used with a modern JS engine, or when bundling with a tool chain that understands ES2015 modules, like Rollup or Webpack.

Sub-projects

Funfix has been split in multiple sub-projects for à la carte dependency management. As mentioned above, you can depend on everything by depending on the funfix project.

These sub-projects are:

funfix-core

npm

Exposes primitive interfaces and data types that need to be universally available, belonging into a standard library.

See JSDoc documentation.

Quick Overview & Usage
npm install --save funfix-core

Exposes types for expressing disjunctions:

Either data type for expressing results with two possible outcome types (a disjoint union)
Option data type for expressing optional values
Try data type for representing the result of computations that may result in either success or failure

Standard interfaces and tools for dealing with universal equality and hash code generation:

IEquals an interface for defining universal equality and hash code
is and equals for using IEquals in tests, or otherwise falls back to JavaScript's equality (== or valueOf())
hashCode for calculating hash codes (for usage in sets and maps data structures) using IEquals, or otherwise falls back to calculating a hash from .valueOf() or from .toString()
isValueObject for testing if a given object implements IEquals

Standard, reusable error types, that help with some common scenarios, working with error types being preferable to working with strings:

DummyError for tagging errors used for testing purposes
IllegalArgumentError for signaling that a given argument is violating the contract of the called function or constructor
IllegalInheritanceError for signaling that inheriting from a certain class is illegal
IllegalStateError for signaling that an illegal code branch was executed and thus something is wrong with the code and needs investigation (e.g. a bug)
NoSuchElementError thrown when the user expects an element to be returned from a function call, but no such element exists
NotImplementedError thrown in case an implementation is missing
TimeoutError thrown in case the execution of a procedure takes longer than expected
CompositeError for gathering multiple errors in a single reference that can expose them as a list

Misc utilities:

applyMixins for working with mixins (i.e. classes used as interfaces, with methods that have default implementations), see Mixins for an explanation
id is the "identity" function

funfix-exec

npm

Contains low level / side-effectful utilities and data types for building higher level concurrency tools.

See JSDoc documentation.

Quick Overview & Usage
npm install --save funfix-exec

Scheduling tasks for asynchronous execution:

Future a lawful, fast, cancelable alternative to JavaScript's Promise
Scheduler the alternative to using setTimeout for asynchronous boundaries or delayed execution

In support of futures and schedulers, ICancelable data types are introduced for dealing with cancellation concerns:

ICancelable and Cancelable for expressing actions that can be triggered to cancel processes / dispose of resources
IBoolCancelable and BoolCancelable for cancelable references that can be queried for their isCanceled status
IAssignCancelable and AssignCancelable for cancelable references that can be assigned (behave like a box for) another reference
MultiAssignCancelable being a mutable cancelable whose underlying reference can be updated multiple times
SingleAssignCancelable for building forward references, much like MultiAssignCancelable except that it can be assigned only once, triggering an error on the second attempt
SerialCancelable being like a MultiAssignCancelable that cancels its previous underlying reference on updates

And also types for expressing durations:

TimeUnit inspired by Java's own enumeration, representing time
Duration inspired by Scala's own type, as a type safe representation for durations

funfix-effect

npm

Defines monadic data types for controlling laziness, asynchrony and side effects. Exposes the most advanced IO implementation for JavaScript.

See JSDoc documentation.

Quick Overview & Usage
npm install --save funfix-effect

The exposed data types:

Eval lawful, lazy, monadic data type, that can control evaluation, inspired by the Eval type in Typelevel Cats and by the Coeval type in Monix, a more simple IO-like type that can only handle immediate execution, no async boundaries, no error handling, not being meant for suspending side effects.
IO lawful, lazy, monadic data type, capable of expressing and composing side effectful actions, including asynchronous, being the most potent and capable alternative to JavaScript's Promise, inspired by Haskell's IO and by the Monix Task

TypeScript or Flow?

Funfix supports both TypeScript and Flow type annotations out of the box.

It also makes the best use of the capabilities of each. For example TypeScript has bivariant generics, but Flow supports variance annotations and Funfix makes use of them. Development happens in TypeScript, due to better tooling, but both are first class citizens.

Contributing

The Funfix project welcomes contributions from anybody wishing to participate. All code or documentation that is provided must be licensed with the same license that Funfix is licensed with (Apache 2.0).

Feel free to open an issue if you notice a bug, have an idea for a feature, or have a question about the code. Pull requests are also gladly accepted. For more information, check out the contributor guide.

License

All code in this repository is licensed under the Apache License, Version 2.0. See LICENCE.

funfix's People

Contributors

alexandru avatar alvaroc1 avatar dmfilipenko avatar gitter-badger avatar greenkeeper[bot] avatar lostintime avatar mcastellini avatar oliverjash avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

funfix's Issues

Traverse

If I have an array of maybes and want to turn that into one maybe with an array. eg:

const x = [Just(1), Just(2)]
// turned into Maybe<[1,3]>

What would be the idiomatic way to do this? I was looking to use traverse but it looks like it's only implemented on the Future

Reconfigure main funfix project to not bundle dependencies

Fixes #83.

The main funfix project bundles everything. This can lead to issues like #83 because the data types in funfix won't be seen by the JS runtime as the data types in the sub-projects. So for example funfix-effect.IO will be a different class from funfix.IO.

Which shouldn't count for much, but because of the duplication we can end up with unforeseen effects, plus this takes users by surprise.

Going forward the main funfix no longer bundles its sub-projects, but treats them as normal (imported) dependencies.

TNone.value typed as undefined breaks the compilation

Given a piece of Typescript code that imports anything defined in disjunctions.d.ts like the following

import { Right } from 'funfix';

Right('foo');

I get this error:

error TS2416: Property 'value' in type 'TNone' is not assignable to the same property in base type 'Option<never>'.
  Type 'undefined' is not assignable to type 'never'.

This is because TNone.value has type undefined while it should be never as TNone extends Option<never>. Somehow the tsc has troubles dealing with the union type defined by Option<A>.value which is undefined | A.

This problem can be fixed by updating the value definition to

public readonly value!: never

I am available to raise a PR if this is the correct way to go.
I am seeing this issue with funfix 7.0.1, compiling with tsc 2.7.2.

implement bracket for resource usage

I put that quickly in shape.
I've done some (Unit) tests that are passing.. (including cancellation)

I'm wondering if I'm on the right path of if there's a fundamental flaw in it?

const bracket = <A>(acquire: IO<A>) => (release: (a: A) => IO<void>) => <B>(
  utilize: (a: A) => IO<B>
): IO<B> =>
  acquire.chain(resource => {
    const doRelease = release(resource)
    return utilize(resource)
      .doOnCancel(doRelease)
      .doOnFinish(_ => doRelease)
  })

An in-range update of rimraf is breaking the build 🚨

The devDependency rimraf was updated from 2.6.2 to 2.6.3.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

rimraf is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Commits

The new version differs by 6 commits.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Upgrade TypeScript to 2.7.x

TypeScript version 2.7 is released.

Upgrading implies some syntax fixes in order to cope with our readonly _A: A encoding, due to the new "strict property initialization" checks. To fix it we have to use "definite assignment assertions".

Published "module" in package.json should point to sources that are transpiled to ES5, except import statements

As per https://github.com/rollup/rollup/wiki/pkg.module, the module field should point to JS that maintains its import/export statements, but is transpiled to ES5 otherwise. Otherwise, any consumers that are using the module field in their build tools (like rollup or webpack when tree-shaking is enabled) must also transpile this dependency.

Generally, all libraries transpile down to ES5, except the module imports so as to not burden consumers.

Reboot funfix-types, move to new lighter top-level project, based on static-land

Moved funfix-types and funfix-laws to project Funland, the packages now being funland and funland-laws respectively.

The new project:

  1. is based on the static-land specification
  2. is light, funland only specifying types with no JS code
  3. is top-level, meaning that data types in funfix-core, funfix-exec and funfix-effect are compatible out of the box

Also all data types in funfix are made to be compatible with Fantasy-Land as well.

BREAKING-CHANGE: the funfix-types and funfix-laws sub-projects are now gone!

An in-range update of rollup-plugin-commonjs is breaking the build 🚨

The devDependency rollup-plugin-commonjs was updated from 9.2.0 to 9.2.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

rollup-plugin-commonjs is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Use 7.0.1 funfix version in Angular based on Webpack

Hi, i want to use funfix in a the Angular framework based on Webpack.

After the install of the dependency npm install --save funfix, the dependency is well added in the nodes_modules and package.json.

Then i use, for example, the pattern Option with the following import :

import {Option} from "funfix";

But i have the following error :

ERROR in node_modules/funfix-core/dist/disjunctions.d.ts(775,14): error TS2416: Property 'value' in type 'TNone' is not assignable to the same property in base type 'Option<never>'.
  Type 'undefined' is not assignable to type 'never'.

Add disjunction types corresponding to data constructors

In Funfix the data constructors are plain functions.

But it's useful to use TypeScript's type guards, in which case exposing some corresponding classes would be useful. As such we'll have:

  • TLeft as the result of the Left data constructor
  • TRight as the result of the Right data constructor
  • TSome as the result of the Some data constructor
  • TNone as the result of the None constant
  • TSuccess as the result of the Success data constructor
  • TFailure as the result of the Failure data constructor

Now we can have methods such as:

isSuccess(): this is TSuccess<A>

And then we can do:

const proc = Try.of(() => 1)
let sum = 0

if (proc.isSuccess()) {
  // type-checks because TypeScript established `proc` is a `TSuccess`
  sum += proc.value
}

Change Higher-Kinded encoding to be compatible with fp-ts

Context: gcanti/fp-ts#252

The encoding is now specified in Funland:

export interface HK<URI, A> {
  readonly _URI: URI
  readonly _A: A
}

export interface HK2<URI, L, A> extends HK<URI, A> {
  readonly _L: L
}

export interface HK3<URI, U, L, A> extends HK2<URI, L, A> {
  readonly _U: U
}

And for Flow:

export type HK3<F, U, L, A> = $PropertyType<$ObjMap<{ Self: [U, L, A] }, F>, 'Self'>

export type HK2<F, L, A> = HK3<F, *, L, A>

export type HK<F, A> = HK2<F, *, A>

An in-range update of funland-laws is breaking the build 🚨

The devDependency funland-laws was updated from 0.1.4 to 0.1.5.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

funland-laws is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Distribute ES5 instead of ES2015

The popular tool webpack uses UglifyJS under the hood, which only works with ES5.

This means that when using webpack to compile and minify an app using funfix, it will fail, because the funfix package is distributed as ES2015.

A workaround is possible: https://stackoverflow.com/a/45088328/5932012

However, it would be good to make this work out of the box for other webpack users. Distributing as ES5 seems to be common practice.

Suggestion: add Option.orUndefined

Sometimes an Option needs to be serialised to T | null or T | undefined. We have Option.orNull for the former. Could we add T | undefined for the latter?

funfix-reactive package wanted ))

Hello!

Just published a package to npm: rx-stream which is basically Monix reactive module port to TypeScript.
Basic builders and operators implemented (empty, pure, range, loop, items, fromArray, never, eval, evalOnce, create, fromTask, fromFuture, fromEval, map, flatMap, mapTask, filter, take, drop, ...).
Sources: https://github.com/lostintime/node-rx-stream

Project is proof of concept, no optimizations, no tests, no docs and some useless stuff may be ported too :(.

Ideally this may land in funfix-reactive module or something and I can spend some hours working on it. With your guidance we can make it happen.

If it sounds good to you - we can start from here :).

Right way to handle a Future that returns an either?

I'm calling f = Future.fromPromise(p) on a promise containing an Either. I'd like to do f.map (or something like that) on the result and operate on the right value of the Either, possibly returning another future. I can't find a built-in function that does this, so I'm resorting to f.flatMap((e) => Future.of(() => fn(e))).

Is there a better way to do this?

Help with compose and point free functions.

Hi!,
thanks a lot for this library, it`s awsome!

I have a question when i want to use composition and point free style:

import { compose, map } from 'ramda';
import { Some, Option, None } from 'funfix';

const optional = ():Option<number> => Some(2);
const add1 = (n:number):number => n + 1; 

/* map example:
*  const map = fn => mn => mn.map(fn); 
*/

const result = compose(map(add1), optional)();
// same of: optional().map(add1)

When I execute it, it works well, but the type inference usually gets complicated.
Is there a better way to do this with funfix?

Thanks a lot!

An in-range update of tsc-watch is breaking the build 🚨

The devDependency tsc-watch was updated from 1.1.36 to 1.1.37.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

tsc-watch is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Commits

The new version differs by 1 commits.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Option.of is non-parametric

You can't pass null or undefined to Option.of. This is super surprising, incompatible with Fantasy Land and breaks the monad and applicative laws.

Is Validated/Validation out of scope for funfix-core

Just ran into the need for a validated type.
I'm considering creating a PR for this.

Questions I have:

  1. Is it beyond the scope of funfix-core?
  2. Should we use scalaz (Validation) or cats (Validated) as a base?

Missing dependencies to build

Hi :)

I just cloned the project and wanted to try to build the project, so I did:

npm install && learn run build

and it couldn't build out of the box. I needed to add 2 dependencies that are not in package.json, which are lodash & shelljs.

Cheers,
Clément.

Add structural equality utils

In funcat-core expose an IEquals interface, along with a universal equals and hashCode functions that works for primitives and that can also check for this interface, inspired by Immutable.js.

mapN should narrow return type to remove null

Given the following code with strictNullChecks enabled:

const a: Option<string> = Option.of(1).mapN(x => 'foo' as string | null);

I get this error:

Type 'Option<string | null>' is not assignable to type 'Option<string>'.
  Type 'string | null' is not assignable to type 'string'.
    Type 'null' is not assignable to type 'string'.

This is because a has type Option<string | null>. I would expect mapN to return Option<string>.

We can fix this by updating the mapN type definition to:

mapN<B>(f: (a: A) => B | null): Option<B>;

What do you think? Perhaps we should also include undefined in the return type of f.

Infinite loop in lerna project setup

In a lerna project setup, when multiple packages depend on funfix-effect (IO), combining IO's from those packages leads to an infinite loop here: https://github.com/funfix/funfix/blob/master/packages/funfix-effect/src/io.ts#L2200.
This is caused by the fact that different lerna packages load different funfix-core module instances and different Try constructors so instanceof doesn't work.

This affects only development stage when packages are linked and can be worked around by using lerna's hoisting feature, so duplicate funfix packages will be moved to top level node_modules folder.

Some ideas to settle this

  1. Use optional check by constructor name, ex:
if (current instanceof Try || (current.constructor && (current.constructor.name === "TSuccess" || current.constructor.name === "TFailure"))) {
  // ...yeah, ugly hack
}
  1. Throw an error in default switch branch here: https://github.com/funfix/funfix/blob/master/packages/funfix-effect/src/io.ts#L2274 with an explanation of the issue, so at least developers know how to workaround it. As CONS - exhaustivity check will be lost for this switch statement :(, may be covered by tests.

  2. Add a warning note in IO's documentation to inform developers about potential issue

Related issue: lerna/lerna#1451 (hosting is not an option for thit guy)

Here https://github.com/lostintime/funfix-lerna-loop is an example repo to reproduce it.

I'm not sure any action should be taken, let's discuss.

`mapN` is gone

Hi @alexandru

When trying to upgrade I noticed mapN was gone, and I was curious what the reasoning behind this was?

Thanks,
Olly

[v.6.2.2] export statement in es5.js

Hi, I am seeing the following error when using es5.js

import { Option } from "funfix-core/dist/es5";

/node_modules/funfix-core/dist/es5.js:1092
export { isValueObject, is, equals, hashCode, hashCodeOfString, id, applyMixins, CompositeError, DummyError, NoSuchElementError, IllegalInheritanceError, IllegalStateError, IllegalArgumentError, NotImplementedError, TimeoutError, Either, Left, Right, Option, Some, None, Try, Success, Failure };
^^^^^^

SyntaxError: Unexpected token export

I wonder if there is something wrong with building es5.js

Project status and future

@alexandru just wanted to check if you plan to work on this project again in the future?

We love the work that you have done with funfix (as we are coming from Scala) however because the project has been stagnant for a while, I am trying to judge if it's better to migrate to e.g. fp-ts or similar.

IO.flatMap never ends when imported from different packages

Currently using funfix in a package which includes only funfix-effect package, but when using that package as a dependency - IO.flatMap never ends.

Dependencies

{
  "dependencies": {
    "funfix": "^6.2.2",
    "funfix-effect": "^6.2.2",
    "funfix-exec": "^6.2.2"
  },
  "devDependencies": {
    "typescript": "^2.6.2"
  }
}

Working example

import { IO } from "funfix-effect"
import { Future } from "funfix-exec"

const one = IO.once(() => 10)
const two = IO.deferFuture(() => Future.pure(20))

one
  .flatMap(_ => two)
  .runOnComplete(() => {
    console.log("done")
  })

This also works

import { IO, Future } from "funfix"

const one = IO.once(() => 10)
const two = IO.deferFuture(() => Future.pure(20))

one
  .flatMap(_ => two)
  .runOnComplete(() => {
    console.log("done")
  })

Not Working (never ends)

import { IO } from "funfix-effect"
import { Future } from "funfix" // <<<< difference

const one = IO.once(() => 10)
const two = IO.deferFuture(() => Future.pure(20))

one
  .flatMap(_ => two)
  .runOnComplete(() => {
    console.log("done")
  })

Plain JS not working also

const { IO } = require("funfix-effect")
const { Future } = require("funfix")

const one = IO.once(() => 10)
const two = IO.deferFuture(() => Future.pure(20))

one
  .flatMap(_ => two)
  .runOnComplete(() => {
    console.log("done")
  })

Problem with funfix in Angular 5 project with IE11 browser

Firstly, thanks for this API, i really like it.

I have a problem. I Use funfix "^6.2.2" in an Angular 5 project (with npm and webpack) and i have an anomaly only in the IE11 browser.

This API works fine on firefox and chrome.

This API is it compatible with IE11 ?

I have the following error in IE 11 :

// "../../../../funfix-core/dist/std.js":
/
/ (function(module, webpack_exports, webpack_require) {

"use strict";
eval("/* harmony export (immutable) / webpack_exports["g"] = isValueObject;\n/ harmony

image

image

Can you help me please ?

Add Semigroup

I'd like to add Semigroup Monoid and Group, but I'm going to do a trial run with just Semigroup to make sure you like my PR. I'll submit it shortly and begin work on Monoid and Group

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.