Giter Club home page Giter Club logo

crocks's Introduction

Build Status Coverage Status Join the chat at https://gitter.im/crocksjs/crocks NPM version

crocks is a collection of popular Algebraic Data Types (ADTs) that are all the rage in functional programming. You have heard of things like Maybe and Either and heck maybe even IO, that is what these are. The main goal of crocks is to curate and provide not only a common interface between each type (where possible of course), but also provide all of the helper functions needed to hit the ground running.

Table of Contents

Installation

crocks is available from npm and is just a shell command away. All you need to do is run the following to save it as a dependency in your current project folder:

$ npm install crocks -S

Usage

There are many options to use crocks to suit the needs of your, projects. When used on the backend or in an environment where size is not a big concern, the entire lib can be brought in and the various elements can be either be plucked off of or referenced by the namespace.

For those cases where size matters, like in the case of frontend bundle building, the individual entities can be brought in. This will ensure that your finished bundles include only what is needed for your application/program.

For using the latter case, refer to the desired function's documentation to find the path in which it resides.

Entire crocks library (CommonJS)

// namespace entire suite to crocks variable
const crocks = require('crocks')

// pluck anything that does not require name-spacing
const { safe, isNumber } = crocks

// still requires entire object, but removes name-spacing
const { and, liftA2 } = require('crocks')

Entire crocks library (JS Modules)

// namespace entire suite to crocks variable
import crocks from 'crocks'

// still imports entire object, but removes name-spacing
import { and, liftA2 }  from 'crocks'

// pluck anything that does not require name-spacing
const { safe, isNumber } = crocks

Single entities (CommonJS)

// require in each entity directly
const and = require('crocks/logic/and')
const curry = require('crocks/helpers/curry')
const isNumber = require('crocks/predicates/isNumber')
const liftA2 = require('crocks/helpers/liftA2')
const safe = require('crocks/Maybe/safe')

Single entities (JS Modules)

// import in each entity directly
import and from 'crocks/logic/and'
import curry from 'crocks/helpers/curry'
import isNumber from 'crocks/predicates/isNumber'
import liftA2 from 'crocks/helpers/liftA2'
import safe from 'crocks/Maybe/safe'

Example

Documentation references: and, curry, predicates (isNumber), liftA2, safe.

// divide :: Number -> Number -> Number
const divide = x => y =>
  x / y

// safeNumber :: a -> Maybe Number
const safeNumber =
  safe(isNumber)

// notZero :: a -> Maybe Number
const notZero = safe(
  and(isNumber, x => x !== 0)
)

// safeDivide:: a -> a -> Maybe Number
const safeDivide = curry(
  (x, y) => liftA2(divide, safeNumber(x), notZero(y))
)

safeDivide(20)(0)
//=> Nothing

safeDivide(20, 0)
//=> Nothing

safeDivide(20, 5)
//=> Just 4

safeDivide('number', 5)
//=> Nothing

Documentation

What is Included?

There are (8) classifications of "things" included in this library:

  • Crocks: These are the ADTs that this library is centered around. They are all Functor based Data Types that provide different computational contexts for working in a more declarative, functional flow. For the most part, a majority of the other bits in crocks exist to serve these ADTs.

  • Monoids: These helpful ADTs are in a class of their own, not really Functors in their own right (although some can be), they are still very useful in our everyday programming needs. Ever need to sum a list of numbers or mix a mess of objects together? This is were you will find the ADTs you need to do that.

  • Combinators: A collection of functions that are used for working with other functions. These do things like compose (2) functions together, or flip arguments on a function. They typically either take a function, return a function or a bit a both. These are considered the glue that holds the mighty house of crocks together and a valuable aid in writing reusable code.

  • Helper Functions: All other support functions that are either convenient versions of combinators or not even combinators at all cover this group.

  • Logic Functions: A helpful collection of logic based functions. All of these functions work with either predicate functions or instances of Pred and let you combine them in some very interesting ways.

  • Predicate Functions: A helpful collection of predicate functions to get you started.

  • Point-free Functions: Wanna use these ADTs in a way that you never have to reference the actual data being worked on? Well here is where you will find all of these functions to do that. For every algebra available on both the Crocks and Monoids there is a function here.

  • Transformation Functions: All the functions found here are used to transform from one type to another, naturally. These come are handy in situations where you have functions that return one type (like an Either), but are working in a context of another (say Maybe). You would like to compose these, but in doing so will result in a nesting that you will need to account for for the rest of your flow.

Contributors

Thanks goes to these wonderful people (emoji key):


Ian Hofmann-Hicks

πŸ’» πŸ“– πŸ“Ή

Ryan

πŸ’» πŸ› πŸ‘€

Andrew Van Slaars

πŸ“– πŸ“Ή

Henrique Limas

πŸ’» πŸ“– πŸ‘€

Robert Pearce

πŸ› πŸ’» πŸ‘€ βœ… πŸ“–

Scott McCormack

πŸ›

Fred Daoud

πŸ‘€

Karthik Iyengar

πŸ‘€ πŸ’» πŸ“–

Jon Whelan

πŸ› πŸ’»

Benny Powers

πŸ“– πŸ’» πŸ‘€

Dale Francis

πŸ’» πŸ‘€

Premith

πŸ“–

Dipen Bagia

πŸ’‘

Andrew Jones

πŸ“–

W. K. Seymour III

πŸ“–

Eliseu Benedito Codinhoto

πŸ“–

NiallArkEnergy

πŸ’» πŸ“–

vidyu

πŸ“–

Michael Wolfenden

πŸ“–

Johan Codinha

πŸ›

Matt Ross

πŸ’»

Jasmina Jacquelina

πŸ“– πŸ’»

Denis Zolkin

πŸ“–

Zhentian Wan

πŸ“–

RichardForrester

πŸ’» πŸ“– ⚠️

Furkan TunalΔ±

πŸ“– πŸ’‘

Paul Desmond Parker

πŸ“–

Rodrigo Erades

πŸ“–

Jamie Dixon

πŸ’»

Basant Pandey

πŸ“–

Course/Videos

Video evilsoft

Video avanslaars

Tutorials

Tutorial rpearce

Examples

Example dbagia

crocks's People

Contributors

amsross avatar area73 avatar avanslaars avatar basantpandey avatar benhormann avatar bennypowers avatar dalefrancis88 avatar deniszo avatar evilsoft avatar futantan avatar henriquelimas avatar jacopkane avatar jakubbarczyk avatar jamiedixon avatar jasminabasurita avatar jonwhelan avatar karthikiyengar avatar michael-wolfenden avatar niallarkenergy avatar premithk avatar richardforrester avatar rolfst avatar rpearce avatar rstegg avatar sauzy34 avatar sunwukonga avatar waldyrious avatar wayneseymour avatar zeucxb avatar zhentian-wan 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  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

crocks's Issues

Add a `both` function to `Arrow` and `Star`

Now that we have first and second implemented properly and add the fanout helper, we should probably add a both function to Arrow and Star.

Both just returns a new Arrow/Star that is set up to be applied to both the fst and snd of a given Pair input.

point-free sigs:

  • both : Arrow a b -> Arrow (Pair a a) (Pair b b)
  • both : Star a (m b) -> Arrow (Pair a a) (m (Pair b b))
  • Add both to Star
  • Add both to Arrow
  • Add a both point-free function
  • Update README

Every function that takes an Array should also allow an Iterable

So each one of these should also take an Iterable:

Helpers

  • mconcat
  • mconcatMap
  • mreduce
  • mreduceMap
  • take (new)

Pointfree

  • filter
  • find (new)
  • head
  • map
  • reduce
  • sequence
  • tail
  • traverse

Since we are now exposing the possibility of infinite values, makes sense to add a take function at this point.

Create a logic folder

Helpers is becoming huge, think it is time to take all Logic based functions and move them into a logic folder. The functions that need to be moved are:

  • ifElse
  • not
  • unless
  • when
  • has (to be added from issue#33

Add the `Endo` monoid

Originally had this as a Comp monoid back in the day but did not constrain to endomorphisims, so I kept running into usage issues with it and eventually removed it all together. Would like to put it back, but constrain to endomorphisims this time, to clear up all the issues I ran into with the old one.

Have you considered a monorepo?

Hi,

Just came by your library through a chance. The functionality looks great. I started to wonder, though, if it would make sense to port it to monorepo style. You would end up with @crocks/combinators and so on. Note that npm made organizations free for open source projects a while ago and you can find tools like Lerna for managing the scheme.

The added benefit would be that this would allow you to split up the current README into something more focused per package. The main README of the project would give an overview of what the library is about and give your documentation some abstraction. You can also aggregate all this as a neat documentation site quite easily.

I wrote a little blog post if you want to learn more about the approach.

Keep up good work. πŸ‘

PS. Let me know if you want to do a little interview for the SurviveJS blog. I've been highlighting gems like this there every once in a while. πŸ˜„

es6 Imports

Hi
Thanks, for very useful library. Any plans to replace require to es6 import? es6 import will be more natural, and since latest versions of chrome and nodejs is supporting them, will work on client and server.

Remove `concat` and `empty` from `Arrow` and `Star`

Does not make sense to use concat for composition.

This was a huge mistake on so many levels. A few things need to be done to make these able to be composed.

  • Remove concat and empty from Arrow
  • Remove concat from Star
  • Add a compose function to Star
  • Add a compose function to Arrow
  • Update pipe to compose Arrows and Stars
  • Update compose to compose Arrows and Stars
  • Add a pipeS helper to compose Arrows and Stars (Semigroupoids)
  • Add a composeS helper to compose Arrows and Stars (Semigroupoids)

Async broken - Uncaught ReferenceError: isFunction is not defined

I don't have any trouble bundling with browserify, but if I bundle with wepback using es6 import syntax like this:

import Async from 'crocks/crocks/Async'

then I get this error in the browser:

Uncaught ReferenceError: isFunction is not defined
    at curry (curry.js:15)
    at eval (isSameType.js:37)
    at Object.<anonymous> (authoring.bundle.js:11045)
    at __webpack_require__ (authoring.bundle.js:556)
    at fn (authoring.bundle.js:87)
    at eval (Async.js:10)
    at Object.<anonymous> (authoring.bundle.js:10991)
    at __webpack_require__ (authoring.bundle.js:556)
    at fn (authoring.bundle.js:87)
    at Object.eval (socketCollabs.js:9)

I can clearly see in the curry.js file that isFunction is very defined, so I'm thinking it might be something in your dependency tree that is confusing poor webpack. Happy to help duplicate the error for you when you get a chance. In the meantime, I've fallen back to Promise, which is not a good match for redux action creators, but it'll do until we get Async working.

Equality should be by value and not by reference

Implement equality by reference by:

  • Adding a pointfree/equals that will compare values inside of Object, Arrays, etc.
  • Update all Setioids to use the value equality when comparing their values
  • Add a isSame predicate function, for a cheap way to check equality by reference,

Note: Will implement equality for all Javascript Types, excluding Map, WeakMap, Set and WeakSet. Those type are commonly used for referential indexing and can be expensive to generally compare. Will leave it up to the user of these type to define their own equality that is optimized for their usage of those types.

Add predicate functions to public API from internal

I find myself wanting to have access to the predicate functions in internal, mostly for use with the new predicate helpers.

  • Create a new preds directory.
  • move all predicate functions from internal to preds.
  • Expose each function on the public api.
  • Back fill any missing specs.
  • Update README to inform dat public

Add linting and hook up to Travis

No point in having all these tests if we cannot get something to run them for us.
Also because I am so particular about style, my make sense to add some linting, JIC people want to start doing the contrib thang.

  • Add linter (probably eslint)
  • Add npm script for running linter
  • Extend test to run the linter in addition to specs
  • Hook up dat Travis ❀️

Add propOr on Maybe

IMHO should be nice to have a propOr function to use in addition to prop on the Maybe module, where we can pass a default value when the prop is not there. Maybe composing 'default' and 'prop' together can be an idea. I can create a PR if you want.

List constructor should behave like `List.of`

Right now we require an Array to be passed into List and this becomes silly when trying to use List as a Monoid in this framework. We will need to provide a fromArray on the constructor, as it is super handy. And while value is needed to work with our Monoid system we got going on, it makes sense to add a toArray to the instance and also add listToArray and arrayToList transformation functions:

  • Remove Array constraint on List constructor, and have it work like of breaking
  • Add fromArray to List constructor
  • Add toArray to a List instance
  • Add listToArray transformation function.
  • Add arrayToList transformation function.

Change up `swap` to not map, just flip the types/values

We should not map on swap, it seemed like a good idea, but that can open us up to all kinds of trouble.

As it sits now, swap is only defined on bifunctors in the framework (which makes sense, if you think about for a long time like I have the past couple days). So because of that if someone want to do that mapping, they can bimap before swap, or just use coalesce as that is what it is for.

`Async.converge` and `Async.all` would be nice

Make things easier on the user.

While it is nice to use the liftA* functions for parallelism, it is such a common pattern with Async that it warrants a couple built ins to avoid a lot of boilerplate "configuration".

converge : (b -> ... -> z -> a) -> [ Async e (b...z)] -> Async e a - Takes a converge/merging function with the same arity of the length of the list of Asyncs passed as the second argument. This will fork the Asyncs in parallel and reject the lot of em if one is rejected. converge should ignore and not fork any Asyncs beyond the arity of the curried convergence function

  • all : [ Async e a ] -> Async e [ a ] - Takes a list of Asyncs and returns an Async that when forked will fork each in parallel and result in an array of the results (just your basic traverse here, nothing fancy, but people like having something called all, so lets give'em what they want). This will reject the lot of em if one is rejected.

Make `Star` a `Monoid`

Star is good, but it could be great

So I punted on making Star a Monoid and I regret that now after using it a bit. I had an idea of doing something like Writer and parameterizing to a specific Monad. So to make one, you do something like:

const MaybeStar  = Star(Maybe)

// MaybeStar(Maybe.of) ??
MaybeStar.empty()

// and of course `concat` will remain basically just flatMapping for left to right composition.

Then we could use mconcat to build a composition:

mconcat(MaybeStar, [ path([ 'a', 'b' ]), safeLift(not(isNull), add(10) ])

Add some additional functions

Someone brought up a good point about reject missing from the lib.
I think it is valuable to give options to the user. Sure, you can always not the predicate to filter, but why make people do that setup if they do not have to. And reject(something) just reads better than filter(not(something)). It is worth it IMO.

Also, in preparation for Free coming soon, would make sense to add composeK for Kleisli composition.

Also because with composeK you will be able to compose Async all pretty like, makes sense to also make a composeP for working on Promise chains.

Might as well add a couple predicates while we are at it, Although, technically to work with the Kleisli bits, the m should be a Monad, but as we are only requiring that chain be present, going to add a isChain predicate. Also would be nice to have a isPromise function, although it seems very imperative to me, some users may find some value.

  • reject on List
  • reject pointfree function, take List or Array to start with
  • composeK helper function
  • pipeK helper function
  • composeP helper function
  • pipeP helper function
  • isPromise predicate function
  • isChain predicate function

Add some transformation functions

Was debating for a while on how to do transformations in this lib.

After a bunch of thinking, I think we should go the helper function route with the possible permutations in a transforms folder. Each function should follow the form: [x]To[Y] (maybeToEither). We can start off with just the Coproducts for now:

  • Either:

    • eitherToMaybe : Either b a -> Maybe a
    • eitherToAsync : Either e a -> Async e a
  • Maybe:

    • maybeToEither : b -> Maybe a -> Either b a
    • maybeToAsync : e -> Maybe a -> Async e a

Add an Async crock

Need something along the lines of a Task or Future in the library. Call it Async and specialize around Async JS functions and nodes CPS style.

Organization by discrete definitions/specs

If crocks will use the common terms of category theory such as Functor, Monoid and Monad, then in order to illustrate the face value of each crock, should there be organization (in the readme, source, or elsewhere) for better API documentation and overall quality?

Add `curryN` for more explicit partial application

While the current recursive curry function is great in most cases, it would be nice to have the ability to explicitly specify the expected arity of a function. This is handy for complicated compositions with curried mutli-ary functions.

Need to correct `first` and `second` for Arrow

No idea what I was thinking with that, but first and second should NOT take a function. It should take nothing and just apply the wrapped function to either the first or second on a pair that the Arrow is ran with.

Add CONTRIBUTORS.md document

Just in case people wanna contribute

This file should contain the following:

  • Steps for working in the dev environment
  • PR submission process
  • Code conventions
  • Spec Guidelines
  • General code of conduct
  • add all-contribs as recommended by @rpearce...So good!

Add branching helper functions to `funcs`

With all these Sum Types going in, we should probably add some branching helper functions so they do not need to be brought in from other libs.

  • ifElse : (a -> Boolean) -> (a -> b) -> (a -> b) -> a -> b
  • when : (a -> Boolean) -> (a -> b) -> a -> b
  • unless : (a -> Boolean) -> (a -> b) -> a -> b

Each takes a predicate as the first argument, then functions that are executed based on the result of the predicates. Each returns a function ready to take a value and either returns the value passed into the function, or runs it through one of the provided functions returning that result, based on the result of the predicate.

These are super handy for lifting into a Sum type:

const { Nothing, Just } = Maybe

const lift = ifElse(
  x => x === undefined,  Nothing, Just
)  

Need to compile ALL THE THINGS and be a better citizen

So Much SMH


So there are a couple issues that can arise from the current build and publish system:

  • Code style is not properly executed in an eval within a webpack bundle. (well that is where the issue was found, there are other places this breaks down. So if ANY of the eval based devtools are used with Webpack, then users are not going to have a good time especially in Safari
  • Also we are being a bit deceptive and not providing our due diligence with how the code is provided. Most people do not babelify their node_modules, so if they are expecting this to work in dear ol Safari or an older browser, then they will be super sad.

There are a few other reasons to do this, but these are big enough to call out.
So this will be an API change to the max:

  • Going to go single dir in a folder called src that will compile to a folder called lib.
  • src will have a flat structure, no crocks/Async.js nonsense. just Async.js.
  • All specs will also be in the same folder, like now.
  • Everything in src will be compiled into lib, specs so testing can be done in the CI environment. This will be tied to npm test.
  • npm run spec:dev will have to doing something different, no idea what that is now, but I do not want to do a full build on every file save. Will probably have to do something silly to get it to run with tape, but we will see.
  • We will ONLY publish the lib folder(sans specs), package.json, README.md and the License.
  • Update the README to show import Async from 'crocks/lib/Async' instead of 'crocks/crocks/Async'
  • Remove the references to the folders like combinators, helpers and what have you.

Documentation

All the Things

  • crocks

    • Arrow
    • Async
    • Const
    • Either
    • Equiv
    • Identity
    • IO
    • List
    • Maybe
    • Pred
    • Pair
    • Reader
    • Result
    • Star
    • State
    • Unit
    • Writer
  • Monoids

    • All
    • Any
    • Assign
    • Endo
    • First
    • Last
    • Min
    • Max
    • Prod
    • Sum
  • Functions

Add some Object helper functions

We should probably have a bunch of helper functions to help users out when playing with Objects.
The following should be provided:

  • hasKey : String -> Object -> Boolean - checks if a key exists on an object.
  • prop : String -> Object -> Maybe a - returns a Just value if the key exists or a Nothing if not
  • propPath : ([ String ] | List String) -> Object -> Maybe a - returns a Just value if the path specified exists or a Nothing if not.

Allow Array for `ap` and `chain`

Array should be able to be passed to the ap and chain pointfree functions. Also concat should concat Arrays like a proper Semigroup.

  • Allow Arrays in ap pointfree
  • Allow Arrays in chain pointfree
  • Restrict Arrays in concat pointfree to ONLY accept other Arrays
  • Allow Arrays in liftA2
  • Allow Arrays in liftA3

List must be constrained to values of the same type

As it sits right now, List is as wild and crazy as your typical JS Array. This is not needed, as we already have an Array and many functions work with Arrays. So lets only allow values of the same type in a List.

Remove `inspect` point free function

There is really no need for it.
All it does it get in the way of inspecting the main crocks namespace.
Should be moved into internal and removed from the main crocks namespace as well.

Add Documentation Style Guide

Just need something on the docs branch to list expectations and provide 🌽sistancy across the documentation.

Conventions, formatting, Layout... that kinda stuffs

Add Star and Costar crocks

As we have Arrow defined, would be nice to get some Monad action in there with Star and Costar. They are basically the same API as provided by Arrow, they just need to deal with the Monad and Comonad flows for dat Profunctor madness.

Do not know how they will sit with being Monoidal like an Arrow that is a -> a as they are locked to a -> m a and m a -> a at their "midpoint". So they will probably not provide value, concat or empty functions.

Remove `value` from `Either` and `Maybe`

Because the types can (and will) vary between Left and Right tags, then there is no way to extract the Left or Unit to match the types. either is the cata for these types and I think it should be the only way to extract, ensuring that the resulting type can be the same regardless of the tag we are pulling from.

While this is totally acceptable in JS, we do not want to encourage bad habits.

Remove Nasty bits from `Pair`

So, back when Pair was creates some horrible things were done, just to get that darn of.
Some cruft needs to be cut from Pair:

  • Remove of
  • Remove value
  • Add toArray
  • add pairToArray transformation
  • add pairToList transformation

EDIT: After some long, hard thought on this, decided to keep the Semigroup constraint for ap, chain and concat. They do in fact provide much value for things like a cheap Writer (which is just a Product type with a Semigroup in its fst.

Add a State crock

Well we have a Reader and a Writer, might as well bring their older brother State into the mix. Should be based off of the Haskell State as descibed here and here.

Fix up Error reporting on `IO.chain`

Right now IO does not report an Error if the function passed does not return an IO.
It should throw inside of the chain function instead of failing when the run function does not exist.

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.