evilsoft / crocks Goto Github PK
View Code? Open in Web Editor NEWA collection of well known Algebraic Data Types for your utter enjoyment.
Home Page: https://crocks.dev
License: ISC License
A collection of well known Algebraic Data Types for your utter enjoyment.
Home Page: https://crocks.dev
License: ISC License
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.
I really enjoy ramda version of reject
and filter
and how they work on Objects as well. Should be easy to add that. So let us do that.
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.
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.
test
to run the linter in addition to specsThis should not happen, a Nothing should be returned if a non-object is passed to prop
.
:smh:
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. 😄
So there are a couple issues that can arise from the current build and publish system:
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 Safarinode_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:
src
that will compile to a folder called lib
.src
will have a flat structure, no crocks/Async.js
nonsense. just Async.js
.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.package.json
, README.md
and the License.import Async from 'crocks/lib/Async'
instead of 'crocks/crocks/Async'
combinators
, helpers
and what have you.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
:
of
value
toArray
pairToArray
transformationpairToList
transformationEDIT: 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
.
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 Async
s passed as the second argument. This will fork the Async
s in parallel and reject the lot of em if one is rejected. converge
should ignore and not fork any Async
s beyond the arity of the curried convergence function
all : [ Async e a ] -> Async e [ a ]
- Takes a list of Async
s 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.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 bifunctor
s 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.
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.
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.
Would be nice to include a Pred
based on the contravariant monoid presented in this article.
We should track and report test coverage.
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#33While it is great and all that the head functions can match the ary-ity of the head functions, it should also match the calling interface. If that head function is curried, than the resulting function from pipe
or compose
should also be curried.
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.
If a function returns an array, it should return the truthy value of the array, which is always true.
erroneous:
const arr = [1,'2','3']
const pred = Pred((x => x.map(isNumber)))
pred.runWith(arr) // [ true, false, false ]
expected:
const arr = [1,'2','3']
const pred = Pred((x => x.map(isNumber)))
pred.runWith(arr) // true
Implement equality by reference by:
pointfree/equals
that will compare values inside of Object
, Arrays
, etc.Setioids
to use the value equality when comparing their valuesisSame
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.
Just need something on the docs branch to list expectations and provide 🌽sistancy across the documentation.
Conventions, formatting, Layout... that kinda stuffs
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.
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
)
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
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.
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 withcomposeK
helper functionpipeK
helper functioncomposeP
helper functionpipeP
helper functionisPromise
predicate functionisChain
predicate functionThis file should contain the following:
As it sits, both traverse
and sequence
point free functions only work with the ADTs. They should also take an Array.
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.
It seems that what the docs call "Helper functions" are exposed under require('crocks').helpers
, but stored in crocks/funcs
, which I didn't expect. For example, if I went looking for require('crocks/funcs/compose')
, it wouldn't be at require('crocks').helpers.compose
For reference:
https://github.com/evilsoft/crocks/blob/master/crocks.js#L28-L30
I find myself wanting to have access to the predicate functions in internal
, mostly for use with the new predicate helpers.
preds
directory.internal
to preds
.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?
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) ])
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))
both
to Starboth
to Arrowboth
point-free functionNeed 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.
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.
concat
and empty
from Arrow
concat
from Star
compose
function to Star
compose
function to Arrow
pipe
to compose Arrow
s and Star
scompose
to compose Arrow
s and Star
spipeS
helper to compose Arrow
s and Star
s (Semigroupoids)composeS
helper to compose Arrow
s and Star
s (Semigroupoids)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:
List
constructor, and have it work like of
breakingfromArray
to List
constructortoArray
to a List
instancelistToArray
transformation function.arrayToList
transformation function.So each one of these should also take an Iterable:
mconcat
mconcatMap
mreduce
mreduceMap
take
(new)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.
So there is no reason we cannot just accept String
and Array
JS Constructors as Monoid
. They will need to be implemented in the following places:
mconcat
mconcatMap
mreduce
mreduceMap
Writer
constructorRight 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.
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 notpropPath : ([ String ] | List String) -> Object -> Maybe a
- returns a Just value if the path specified exists or a Nothing if not.updated to @evilsoft's reply, add a fold
function:
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.
The documentation needs an API or some sort of table-of-contents for sanity
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.
We should make a specialized Validation crock for accumulating Validations.
import Maybe from 'crocks/crocks/Maybe'
should be
import Maybe from 'crocks/Maybe'
We are going with the prop
theme here, so this should be a bit more 🌽sistant.
Array should be able to be passed to the ap
and chain
pointfree functions. Also concat
should concat Arrays like a proper Semigroup.
ap
pointfreechain
pointfreeconcat
pointfree to ONLY accept other ArraysliftA2
liftA3
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.