These are chat archives for ramda/ramda

29th
Apr 2015
Jethro Larson
@jethrolarson
Apr 29 2015 07:56
Almost to 2k stars!
Simon Friis Vindum
@paldepind
Apr 29 2015 09:28
Will there be gifts as well this time? :)
Raine Virta
@raine
Apr 29 2015 09:50
submitted ramda to r/javascript, it's been a while since the last time
cotne nazarashvili
@thecotne
Apr 29 2015 10:12

how can i do deep merge with ramda?

expected behavior someDeepMergeImplementation({user:{name:'cotne'}}, {user:{lastname:'nazarashvili'}}) // => {user:{name:'cotne', lastname:'nazarashvili'}}

Brandon Wilhite
@JediMindtrick
Apr 29 2015 10:33
got a ramda-fantasy question...assuming this is the right place to ask
I want to use a monad for error handling instead of exceptions, first Either seems like the right tool for this task, yes or no?
Second, I'm having a hard time figuring out how to use Either. I've been reading the code and tests, but everything is so terse and centered around the fantasy-land spec.
Can someone share an example? I want me either to either contain an Error (the built-in js class) or another value.
*my Either
if(R.is(Error,myEither)){
   //do something with the error
}else{
   //do something with the value
}
Raine Virta
@raine
Apr 29 2015 10:43
Hardy Jones
@joneshf
Apr 29 2015 10:48
@JediMindtrick yes you can (should?) use Either for something like that
a good idea with an ADT like Either is that you should let the data type do most of the work.
so in your example there, you'd want to rely on the mehtods Either provides for you
eitherVal.bimap(erroHandler, valueHandler)
but
part of the point with Either is that you want to get out as soon as you have an issue, but just continue on in case everything is fine
this is where the chain method comes into play
Hardy Jones
@joneshf
Apr 29 2015 10:53
eitherVal.chain(firstComputation).chain(secondComputation).chain(...)
if any of those copmutations returns a Left, it's going to stop at that point
if they all return Rights, then itll continue down the chain
and of course if you want to rip the value out of there you can do:
eitherVal.chain(firstComputation).chain(secondComputation).chain(...).bimap(errorHandler, valueHandler)
or make it vertical if you like
eitherVal
  .chain(firstComputation)
  .chain(secondComputation)
  .chain(...)
  ...
  .bimap(errorHandler, valueHandler)
Raine Virta
@raine
Apr 29 2015 10:56
what's the return type of bimap?
Hardy Jones
@joneshf
Apr 29 2015 10:59
bimap : Either a b => (a -> c, b -> c) -> c
or so
it picks whichever side of the Either it's called on, and evaluates the appropriate function
Left(3).bimap(R.add(10), R.add(0)) //=> 13
Raine Virta
@raine
Apr 29 2015 11:02
useful
Brandon Wilhite
@JediMindtrick
Apr 29 2015 11:06
so ```
Conceptually I get most of that, but where I'm struggling is with the very basics of getting started. So baby steps...I have a function, and the function will return either an Error or a number. So function needs to return an Either. What does that function look like?
Brandon Wilhite
@JediMindtrick
Apr 29 2015 11:12
var add = function(a, b) {
    if(a < 2){
       //make the either contain an error
    }else{
      //make the either contain a + b
    }
}
I probably should have started there anyway
My thought was that we wouldn't necessarily explicitly handle setting the Error/value, but that we would somehow pass add in, and if the function returned a value great, otherwise it would contain a pre-defined error.
var myEither = Either( a,b  => { 
    if(a < 2)  {
        return null;
    }else{
        return a + b;
    }
}, new Error('hey, this will not work'));
what am I missing?
Hardy Jones
@joneshf
Apr 29 2015 11:17
I dunno what kind of fancy stuff the Either constructor for RF does, but what's wrong with just constructing the value?
Stefano Vozza
@svozza
Apr 29 2015 11:17
is the function not just this:
var add = function(a, b) {
    return a < 2 ? Left(new Error('hey, this will not work') : Right(a + b)
}
Hardy Jones
@joneshf
Apr 29 2015 11:18
as @svozza says
Scott Christopher
@scott-christopher
Apr 29 2015 11:42
Or if you're dealing with existing JS that can potentially throw, you can wrap it in something like:
function tryEither(fn) {
  return function () {
    try {
      return Right(fn.apply(this, arguments));
    } catch (e) {
      return Left(e);
    }
  };
}

tryEither(unsafeFunction)(varA, varB, etc);
Brandon Wilhite
@JediMindtrick
Apr 29 2015 12:00
Starting to gel a bit more now
so with either of these last two, we now do something like...?
if(R.is(Error,myEither)){]else {}
or is that where the bimap() comes in?
.bimap(=> { /handle error/}, => {/handle success/});
Scott Christopher
@scott-christopher
Apr 29 2015 12:05
bimap will return a new Either that is the result of calling the the left or right function, depending on whether it is a Left or Right instance of Either.
Raine Virta
@raine
Apr 29 2015 12:08
Scott Christopher
@scott-christopher
Apr 29 2015 12:08
So Left(err).bimap(e => e.toString(), R.identity); // => Left("Error message")
and Right("Success").bimap(e => e.toString(), R.identity); // => Right("Success")
Brandon Wilhite
@JediMindtrick
Apr 29 2015 12:10
looking at the code, I think the question I'm asking is ```
if(R.is(Left,myEither)){
    //handle error using myEither.value
}else{
    //handle success using myEither.value
}
or some more function-y variant, I suppose
gonna test all that out...but I think I have my answer, unless someone wants to correct it...THANK YOU all!!
Scott Christopher
@scott-christopher
Apr 29 2015 12:15
To answer your question, it kinda depends on how you want to handle the success and error cases
If you want to normalise to some new value, depending on Left or Right, then you'd want something like a fold on Either, which I don't believe exists on the ramda-fantasy Either
Which can be thought of: Either[A, B] -> (A -> C) -> (B -> C) -> C
Brandon Wilhite
@JediMindtrick
Apr 29 2015 12:18
that makes sense... @joneshf 's snippet/comments on chain now make more sense as well
Scott Christopher
@scott-christopher
Apr 29 2015 12:18
So very similar to bimap, except you get a plain value out, rather than another Either instance
Brandon Wilhite
@JediMindtrick
Apr 29 2015 12:20
@scott-christopher cool. You have been very helpful; thanks.
Scott Christopher
@scott-christopher
Apr 29 2015 12:21
:) Good luck with it all.
Brandon Wilhite
@JediMindtrick
Apr 29 2015 12:35
@raine I may switch over to folktale just b/c the docs are a bit better, thanks for the link.
Raine Virta
@raine
Apr 29 2015 12:38
yeah, i've used folktale's data.maybe with great success with ramda
stuff like this works i think because ramda's map implementation looks for #map in the container and delegates
R.map(R.add(1), Just(1)) // => Just(2)
Scott Sauyet
@CrossEye
Apr 29 2015 14:27
@thecotne there is no deepMerge function right now. Although I wouldn't mind getting a PR on this, I think you might be underestimating the complexities that could arise.
cotne nazarashvili
@thecotne
Apr 29 2015 14:56
@CrossEye i know it's complex task but we can port this functionality from others (jquery has this for example)
Raine Virta
@raine
Apr 29 2015 16:49
var deepMerge = require('lodash.merge') :sparkles:
Hardy Jones
@joneshf
Apr 29 2015 17:24
nice
Scott Sauyet
@CrossEye
Apr 29 2015 17:57
@thecotne I'm suggesting that the general problem is harder than current implementations let on. Look at the implementation from @raine's little joke. The function takes any number of objects (greater than zero), then an optional callback to allow the user to handle the cases the function is not able to, then another optional argument to serve as a binding for that customizer. It mutates is first parameter, and still cannot (without help from that callback function) handle constructed subobjects.
Scott Sauyet
@CrossEye
Apr 29 2015 18:04
This does not at all sound like a good model for Ramda.
Hardy Jones
@joneshf
Apr 29 2015 18:10
what would it need to do?
you'd need to know if two keys are equal
if they aren't, then you can just add both values
if they are equal, you have to decide how to merge the values
Scott Sauyet
@CrossEye
Apr 29 2015 18:24
So if objA has a shape property created from new Square (4), which because of its inheritance from Rectangle had two public properties, width and height, both set to 4, and objB has a shape property with a public height property of 7, what would you expect in the merged object? A 4 x 7 square?
Hardy Jones
@joneshf
Apr 29 2015 18:55
oh right, js treats everything as an object
wait, wouldn't that also blow up for arrays?
Scott Sauyet
@CrossEye
Apr 29 2015 19:05
There are interesting questions for arrays too, but I think they're more readily soluble.
Brandon Wilhite
@JediMindtrick
Apr 29 2015 19:20
I've always been interested in diff'ing two JSON objects...not quite the same problem but with some similarities
even more specifically, generating a diff and patch...something along the lines of this rfc http://tools.ietf.org/html/rfc6902
Scott Sauyet
@CrossEye
Apr 29 2015 19:27
@JediMindtrick: Yes, clearly related ideas.I think both can be done on a wide sunset of JS objects. But they're are significant limitations.
Brandon Wilhite
@JediMindtrick
Apr 29 2015 20:41
Y, that's one of those things where human intelligence looks at it and says "this should be easy" but when you get more rigorous with it you uncover all sorts of edge cases and contradictions.
Hardy Jones
@joneshf
Apr 29 2015 21:02
I've gotta jet in a sec, but i've been wondering about rf.
what's its purpose? where does it fit in the grand scheme of things
at the moment it doesn't seem to offer anything over something like folktale
and the liftN issue doesn't seem to add much value either when compliant implementations exist elsewhere
does it do something like auto-{un,}currying?
Michael Hurley
@buzzdecafe
Apr 29 2015 21:09
@joneshf it was a project so i could learn about this stuff. then ramda became popular and it's profile was raised
Scott Sauyet
@CrossEye
Apr 29 2015 22:02
Ramda itself started the same way. @buzzdecafe and I started it (and its predecessor) as a way to see what we could do to bring a more FP style to JS, and to learn more about FP. It was a sleepy little project for a year and then took off in a hurry a year ago.