ramda / ramda-fantasy Goto Github PK
View Code? Open in Web Editor NEW:ram::sparkles: Fantasy-Land compatible types for easy integration with Ramda.js
License: MIT License
:ram::sparkles: Fantasy-Land compatible types for easy integration with Ramda.js
License: MIT License
Please, some examples of use of these cuties, thanks.
Would be nice to download this using bower
Hello @CrossEye @buzzdecafe @davidchambers!
I don't know what the plan for ramda-fantasy
is but recently I have begun using monads in my programming and since I love ramda
I would also love for the ramda community to maintain its own type library unless the maintainers of ramda think that there are better alternatives out there in the wild.
Looking at this repo, what I initially see is missing is:
I am of course willing to help our here, to contribute and learn more about how to do functional programming right. I am curious what the rest of the people invested in ramda thinks.
Just discovered this https://github.com/gcanti/flow-static-land. I have no affiliation. Just would be (maybe?) awesome to add static types?
Commuting a list of Maybes results in a Nothing if any of the elements if a Nothing:
> R.commute(Maybe.of, [Maybe.Just(1), Maybe.Just(2)])
Maybe.Just([1, 2])
> R.commute(Maybe.of, [Maybe.Just(1), Maybe.Just(2), Maybe.Nothing()])
Maybe.Nothing()
Commuting a list of Eithers results in a Right whose value is a list containing each Right's value:
> R.commute(Either.of, [Either.Right(1), Either.Right(2)])
Either.Right([1, 2])
> R.commute(Either.of, [Either.Right(1), Either.Right(2), Either.Left('XXX')])
Either.Right([1, 2])
Forgive me if there is an obvious answer for this (I'm new to Maybes and Monads). If you call 'map' on a Just and that function produces a 'null' or 'undefined' shouldn't a new Nothing be created as opposed to a Just that contains a null value?
Example:
maybe([12]).map(function() { return null; });
/=> Just { value: null }
https://github.com/ramda/ramda-fantasy/blob/master/src/Maybe.js#L47
Should Reader.ask
equal Reader(R.identity)
? so the following would work
const append = str => Reader.ask.map((strToo) => str.concat(' ', strToo));
const greet = R.compose(R.chain(append), Reader.of);
greet('hello').run('world'); //=> hello world
rather current with Reader.ask = Reader(R.always)
const append = str => Reader.ask.map((strToo) => str.concat(' ', strToo()));
const greet = R.compose(R.chain(append), Reader.of);
greet('hello').run('world'); //=> hello world
you need to call strToo()
...
Hello!
Firstly, this project is great, and I've been playing with it for a few weeks. I have to ask, though: is there a reason why Maybe doesn't have a concat
method defined? As I see it, the concatenation would work like this:
Nothing `concat` Nothing = Nothing
Nothing `concat` x = x
x `concat` Nothing = x
(Just x) `concat` (Just y) = Just (x `concat` y)
I'm more than happy to submit the PR if this sounds reasonable - just thought I'd double check in case I'd missed something obvious :)
Could that be done?
I think the version should be changed to something low, like 0.1.0
but I would really like it to be on npm just so that it will be easy to install to other projects for trying out. We could also update the readme to disclaim that this is pre alpha or what we would like to call it and that the API is running a high risk of being changed in this phase.
analogous to Maybe
I miss good way to wrap nullable values in the Maybe Monad.
Option Types nowadays usually provide a static constructor ofNullable, which returns Just(x) or Nothing() depending on the value given.
I don't want to use Maybe(x) directly, since I want to show more explicitly that my wrapped value is nullable.
I could implement ofNullable if there is an agreement to support this.
or just merge with sanctuary? stop duplicating effort?
This started as issue 1048 at the ramda repository. I'm working with 2-dimensional arrays where the nested arrays are all length-2, I've imagined them as being tuple pairs. My first needs were the fst
and snd
functions in Ramda to handle those pairs. Later we talked about creating a Pair
or Tuple
functor, which might be more useful in general.
I've fooled around a bit in this Gist, however I'm not satisfied with the results so far. (Is my use of .of()
correct? Do I understand the Applicative specification at all?)
But lets first answer: what should the API be?
Given an array:
var pair1 = Pair(['one', 2]);
fst(pair1); //=> 'one'
snd(pair1); //=> 2
Given 2 arguments:
var pair2 = Pair('one', 2);
fst(pair2); //=> 'one'
snd(pair2); //=> 2
Creating instances with Pair.of()
:
var text = ['one', 'two', 'three'], numbers = [1, 2, 3];
R.map(Pair.of, R.zip(text, numbers)); //=> [Pair, Pair, Pair]
@DrBoolean suggested an array-friendly solution, which plays nice with R.nth()
and R.head()
:
var _Tuple = function(x, y) {
this[0] = x;
this[1] = y;
this.length = 2;
}
As a last remark, I personally don't think I'm qualified, since my functional programming on the level of algebraic structures is afaik not good enough. I've started learning Haskell but I'm mainly still figuring things out. I would love to help out, but don't let me slow you down.
I've been unable to get the most basic example of a working Future to work. I would suggest updating the documentation with a simple working version of a Future that returns a value.
Future.of((reject, resolve) => {
setTimeout(() => resolve('success'), 500)
}).fork(console.error, console.log)
// log: 'success'
// output: undefined
If fork
is necessary to evaluate a Future, but fork
can only return undefined
, how is it possible to unwrap the computed value?
its been a while since an NPM version was released.
Right now I have a projected pointed directly at github, and I'm getting flak for it, would you guys be able to release a new version?
from this comment: ramda/ramda#1638 (comment)
anyone have strong feelings one way or the other on the name ramda-fantasy
? Possible alternatives (in no particular order) include:
E.g. give me the string after the question-mark. So if we do NOT have a
question-mark, we expect the Maybe monad to handle the undefined gracefully.
But following test fails:
expect(R.compose(
R.map(R.nth(1)),
R.map(R.split('?')))(Maybe('')))
.toEqual(Maybe.Nothing())
We get something like:
Error: Expected { value: undefined } to equal {} + expected - actual -{ - "value": [undefined] -} +{}
So the map-method of Maybe should not use this.of(x) but Maybe(x) instead.
Are we good with releasing current master as 0.4.0?
Shouldn't Left have a map that returns self?
If I have an Either and I call map on it, I want it to Either do the mapping or if it's a Left than return the Either with the left in it. Don't I?
Thanks,
R
var n = Maybe.Nothing();
n.x = "mutated";
Maybe.Nothing().x; // "mutated"
this seems bad. I think we should rethink how Nothing
is implemented. It relies too much upon the good behavior of the developer.
Moved from ramda/ramda#677
@donnut reported:
In v0.7.0 the following (simplified) snipped worked fine.
var io1 = IO.of(2);
var io2 = IO.of(5);
R.lift(function(a, b) { return a + b;}, io1, io2).runIO(); // => 7
In v0.8.0 it throws an error because R.lift returns an empty array instead of a IO instance. I took a quick look at the differences between the two versions, but I can find any reason why lift stopped doing what it did previously.
Note: It is amazing how much work you guys have done in a couple of weeks!
Straight out of #70 (comment) but contiuing the discussion here:
I find this very interesting. It has bothered me that there are two ways of handling errors, Future and Either. What would be gained from removing the forking from futures and replacing it with run
or something similar?
Once #33 is in, let's publish
Are there any plans to implement State and Writer?
then setoid can come off the table on README
Currently Future.prototype.equals
always returns true.
From the fantasy-land Monad specification.
A value which satisfies the specification of a Monad does not need to implement:
- Apply's ap; derivable as function(m) { return this.chain(function(f) { return m.map(f); }); }
- Functor's map; derivable as function(f) { var m = this; return m.chain(function(a) { return m.of(f(a)); })}
This could mean that we could create this type:
function Monad() {}
Monad.prototype.ap = function(m) { return this.chain(function(f) { return m.map(f); }); }
Monad.prototype.map = function(f) { var m = this; return m.chain(function(a) { return m.of(f(a)); })}
.. and then implement stuff like
function Maybe() {};
inherits(Maybe, Monad);
function Just() {};
inherits(Just, Maybe);
Just.prototype.of = ...
Just.prototype.chain = ...
This also removes the need to test if the type has all the monadic functions. All that is required is to assert it is an instance of Monad
.
There are also other examples of functions that can be derived from other types.
Good/bad idea?
I was trying to upgrade to ramda 0.17.x
but the tests for IO
fail. I can't really see why. Does anyone else have an idea?
I am transpiling my es6 to AMD modules with Babel. I may take a shot at putting this lib in the UMD wrapper so it will work with both flavors of modules.
Hey there.
In Chapter 8 in @DrBoolean's book, it is told about Maybe:
Maybe.of({
name: 'Boris',
}).map(_.prop('age')).map(add(10));
//=> Maybe(null)
yet when I execute it with ramda-fantasy
i get:
Should it be this way? is it a bug? Isn't Maybe
checks nulls every time?
Should we merge RF and Sanctuary?
What would a merger of RF an Sanctuary look like?
The problem could be ignorance on my part. I occasionally use the docs to familiarize myself with new concepts and I was just looking over the docs for composeK and attempted to try out the example in the REPL.
I understand that there are trade offs between succinct examples and providing clarity for users new to FP. I was comfortable filling out the missing parseJson
and get
functions and even looking up Sanctuary to understand Maybe. Even after having done that though there are still several things that I don't understand about the example and I'm wondering if it's a lack of understanding on my own part of something wrong with the example, Ramda or Sanctuary.
Here is my code (http://goo.gl/4aCLE4):
// parseJson :: String -> Maybe *
// this should work :
//var parseJson = S.encase(JSON.parse);
// but does not, it throws a type error.
// instead you have to unwrap the maybe and rewrap it?
var parseJson = str => {
var result = S.encase(JSON.parse, str)
return Maybe.of(result.value);
}
// get :: String -> Object -> Maybe *
var get = str => obj => {
return Maybe.of(obj[str]);
}
var getStateCode = R.composeK(
R.compose(Maybe.of, toUpper),
get('state'),
get('address'),
get('user'),
parseJson
);
getStateCode(Maybe.of('{"user":{"address":{"state":"ny"}}}'));
//=> Just('NY')
//getStateCode(Maybe.of('[INVALID JSON]'));
//=> Nothing()
Two primary questions:
S.encase
is curried by default and returns a Maybe
but the error message seems to indicate that it is not of type Maybe b
?Maybe.of
but it seems that S.toMaybe
is better since it handles undefined
being Nothing
. I've had several attempts on the invalid JSON where the composition, R.compose(Maybe.of, toUpper)
failed because toUpperCase is not a function on undefined
. The code seems to be written with the assumption that undefined
would be Nothing
and therefore not have the chain
method invoked. Is that correct?Thanks to anyone who can provide insight :).
Should there be an equivalence of a finally
statement on futures? I recently used that with promises and I wondered how I would solve the same situation with futures. Folktale has a cleanup method but it is supplied with the constructor. To me that seems a bit weird. Should it not be called together with fork
?
Thoughts?
wouldn't you want to implement the Maybe
constructor and the Maybe.of
method like this:
function Maybe( x ) {
return ( x === null || x === undefined ) ? _nothing : Maybe.Just( x );
}
Maybe.of = function( x ) {
return new Maybe( x );
}
Currently if I do something like this
Maybe.of( undefined );
I get back a _Just {value: undefined}
The package.json
shows a version range up to 0.20
but bower.json
is fixed at 0.14
. ?
Is there a particular reason holding back the dependency for bower RF to be in line with 0.19.x
Ramda?
Unable to find a suitable version for ramda, please choose one:
1) ramda#^0.14.0 which resolved to 0.14.0 and is required by ramda-fantasy#0.4.1
2) ramda#^0.19.1 which resolved to 0.19.1 and is required by my-project
Cheers
No big deal, but perhaps worth raising here.
Noticed the toString on Maybe is displaying _Just rather than Just. Haven't checked other Types to see if they exhibit the same behaviour. It would be cleaner if it returned a toString of what the user is workiing with - Just and Nothing in this case.
const nestedIceCream = Maybe(Maybe('Ice cream'));
console.log(nestedIceCream);
// _Just { value: _Just { value: 'Ice cream' } }
Thoughts?
Unnecessary error catching is something that, IMO, we should avoid in Future/Task implementations. e.g.
function createFuture() {
return new Future(function computation(reject, resolve){
setTimeout(() => {
resolve('hello');
}, 0);
});
}
createFuture().fork(
left => { console.log('left', left.message); },
right => { console.log('right', right); throw new Error('boom'); }
);
This example will log in the console:
right hello
left boom
This is not good as it's completing the future twice and mixing rejections with unexpected errors (something that Promises do). If there is code that might be prone to throwing an error (such as JSON.parse or accessing nested props in an object) THAT code should get wrapped in a try/catch. The Future/Task should have no opinion on error catching.
I did some experimentation today and hacked together futurify
and futurifyAll
functions inspired by bluebirds promisify and promisifyAll.
I was wondering if this is of interest for ramda fantasy. Would they be something that we would want to put in this project, a separate utility-project or not in ramda at all?
Maybe.of should not create "Just" when we pass null.
Maybe.of(null) should return Nothing()
I was wondering if this is an issue or not, but the documentation shows the use of Either.either but this method is not included in the latest release (0.4.1) even though the commit for this addition is from 2015, I'm just wondering if you could add this to the release because I downloaded via NPM and trying to use it found out it is not available in the latest tagged release only in the master.
Reader/T
, State/T
implement Chain so it's possible to also implement ChainRec.
As briefly discussed on Gitter, the current Applicative implementation for Tuple
doesn't behave.
Tuple.of(R.identity).ap(Tuple.of({}));
//=> [TypeError: function f1(a) { ... } be a semigroup to perform this operation]
I currently see three options here:
Apply
by dropping of
.ap
implementation to:_Tuple.prototype.ap = function(m) {
return Tuple(this[0](m[0]), this[1](m[1]));
};
of
implementation to something like:Tuple.of = function(x) {
return Tuple({ concat: R.identity }, x);
};
I think I'd like to see Tuple
take on option 2 and if desirable, introducing a Writer
type that can implement option 3, but I'm keen to hear the thoughts of others.
Please update it!
In #88, for example, we're adding:
Maybe.isJust = function(x) {
if (typeof x.isJust !== 'function') {
throw new TypeError('invalid type given to Maybe.isJust');
} else {
return x.isJust();
}
};
With sanctuary-def, we could write:
// Maybe.isJust :: Maybe a -> Boolean
Maybe.isJust =
def('Maybe.isJust',
{},
[$Maybe(a), $.Boolean],
function(maybe) { return maybe.isJust(); });
I think that this library is quite useful in its current state but the impression is not that good when looking at the code. One reason is the lack of documentation and structure. I have never used jsdoc myself (other than to write it in working environments). Is there anyone with knowledge that knows what it will take to generate documentation? I think that a site with published documentation would greatly improve the status of this project.
As of fantasyland/fantasy-land#152 implement ChainRec specification.
MonadRec instance for either in purescript might be usefull
Here is implementation of ChainRec for folktale/data.task
with tests myght be usefull for Future
(it's not quite correct as it is not handling cleanup stuff of the data.task but without that it works well)
I would create PR when have time.
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.