These are chat archives for ramda/ramda

14th
Feb 2017
Keith Alexander
@kwijibo
Feb 14 2017 07:42
@dtipson :D
@Bravilogy
const maybeToFuture = m => m.map(Future.of).getOrElse(Future(()=>{}))
Future.of(Maybe.of(42)) //=> Future(Maybe(42))
.chain(maybeToFuture) //=> Future(42)
Bravi
@Bravilogy
Feb 14 2017 07:52
@rickmed yeah I've seen Dr. Boolean's stuff. I may need that liftA2, not sure :D I'll give it a try
Galileo Sanchez
@galileopy
Feb 14 2017 13:43
I've been playing around a bit with fp, I think I get composition, and use it often, also I have a good grasp of arg ordering to harness currying, and ramda was an excellent way to start doing fp with javascript, and I learnt a lot of concepts just by reading their docs, also I've been playing a bit with EventStream and I think I kind of get them, but I still lack a good understanding of Maybe, Either, Future, Task, IO and don't really know where, when and how to use them. The only thing I think I know is that all of those types has something in common and that they're very different from Transducers, (which I don't get yet either). What would be a good reading to get a grasp of those concepts? I tried this https://www.gitbook.com/book/drboolean/mostly-adequate-guide/details, but it get's hard to read after a while.
I also tried reading the Fantasy Land spec, but that was too much already xD
What would you recommend to read to fill in that gap?
Galileo Sanchez
@galileopy
Feb 14 2017 13:53
Perhaps the reason why it's been easier learn what I've learnt is because it is easy to use the way I usually work, which is mostly writing express middlewares, and I kind of get the feeling that starting to use those other types will change the way I interface my middlewares for some reason? Perhaps instead of making composable mws to be able to mix an mingle them at the route definition I should change that to start writing small functions that do the same but forego the mw interface, and do my mix and mingle at the controller level exposing just one mw per route?
idk is just an intuition that I won't be able to make it work without changing the style I've grown fond of.
Keith Alexander
@kwijibo
Feb 14 2017 14:21

@galileopy https://jaysoo.ca/2016/01/13/functional-programming-little-ideas/ is an excellent blog post about working with Maybe, Task, Either etc

I've also started writing a blog about the basics of using these types in a practical setting - https://kwijibo.github.io/uncertain-values/ tries to explain Maybe - I'd welcome any feedback you might have

Keith Alexander
@kwijibo
Feb 14 2017 14:37
Transducers are a neat technique for composing reducer functions (functions you pass to .reduce, of the form (a, b) -> a). This can be used to achieve loop fusion: mapping and filtering multiple times over the same list in a single iteration.
However the consensus on the ramda issue tracker at least, is that it's not a technique commonly needed - so I wouldn't worry about understanding them straight away.
Adam Szaraniec
@mimol91
Feb 14 2017 14:51
I saw there was some question about ramda, some days ago. I would like to ask also
Map can work on objects - its great
Why Reduce can not? Any way to achieve similar 'result'. Reduce function could just accept value,key
Bernhard Wang
@zwc
Feb 14 2017 15:02

@mimol91: You can always use toPairs to make an object as a list. I imagine the reason it does not work on objects is that objects can be nested.

Consider this, sum up all values inside an object.

const obj = { a: 1, b: 2, c: 5 };

const addValue = (acc, val) => {
    acc += R.last(val);
    return acc;
};

const sum = R.reduce(addValue, 0, R.toPairs(obj));
The addValue can probably be written smarter ... but I'm a Ramda newb
Adam Szaraniec
@mimol91
Feb 14 2017 15:06
Clever =)
Rick Medina
@rickmed
Feb 14 2017 15:07
@mimol91 that has been greatly discussed in the ramda repo. ramda/ramda#2046
Adam Szaraniec
@mimol91
Feb 14 2017 15:07
Hmm array can be nested too
@rickmed Thanks for link
I m happy that not only me was wondering about it =)
Rick Medina
@rickmed
Feb 14 2017 15:10
short story: the problem is in what order the keys/values are reduced?
Drew
@dtipson
Feb 14 2017 18:35
@galileopy one thing to realize about Either/Maybe/Task/etc. is that they all allow you to just keep composing together functions even in cases when it would ordinarily seem impossible.
Like, if you have a function that requires some discrete type as input, but otherwise breaks, you can't possibly compose it together with a function that sometimes returns that type but sometimes doesn't, right?
But if you have that function "always" return an Either (either a Left containing the wrong type, or a Right containing the right type) then instead of a bare ambiguous value, then you can just "always" just .map your function over the container, and the container type takes care of the ambiguity for you. If you ever want to resolve the ambiguity then you'd just .fold out of it by saying what you'd want to happen if it were a Left or a Right, usually resulting in a single value of some discrete, known type, the same type either way it went
Task is similar, it's just that it allows you to keep composing functions together even in the case where some of those functions might take time to return
Galileo Sanchez
@galileopy
Feb 14 2017 20:25
@dtipson @kwijibo Thanks both of you, for your input, That composition tip made me realize of something that I haven't thought of before, that it is the same thing doing Maybe.of(someFn(param)).map(otherFn), than doing compose(map(otherFn),Maybe.of, someFn). I'll start reading now @kwijibo :)
Galileo Sanchez
@galileopy
Feb 14 2017 20:40
ok, and (one of?) the cool thing :tm: about Tasks vs Promises is that fork method, which separates definition from execution, which would be somehow like wrapping a promise inside a function?
Keith Alexander
@kwijibo
Feb 14 2017 20:43
yes exactly
Galileo Sanchez
@galileopy
Feb 14 2017 20:43
:scream: and lift is just map???
Keith Alexander
@kwijibo
Feb 14 2017 20:44
map is an unary lift
Galileo Sanchez
@galileopy
Feb 14 2017 20:49
what do you mean? lift is not unary?
Keith Alexander
@kwijibo
Feb 14 2017 20:50
lift can have different arities
whereas map can only have an arity of one
with lift you can do
lift(R.add)(Task.of(2), Task.of(2)) //=> Task.of(4)
Drew
@dtipson
Feb 14 2017 20:52
you can basically think of .forkas being similar to .fold for async types as well: Once you fold, you're exiting the context of the type. Same with .fork
fork just happens to have the ability to exit in the type at some unknown point in the future (as well as being effectful/impure)
Keith Alexander
@kwijibo
Feb 14 2017 21:18
Another way to think of Task is as an interface for composing continuation-passing functions (like @dtipson said, monads are all about composition)
there are a few different implementations with different APIs, but what they have in common is they accept a function that expects callbacks (one for success, one for failure, and possibly others for, eg cancellation, depending on the implementation), and let you compose that function with either unary functions (via map) or other functions of the same shape (via chain)
and then when you call .fork(...callbacks) (.run() in some implementations) you are calling that composed function
Drew
@dtipson
Feb 14 2017 21:36
And unlike Promises, since they don't try to smash together the concept of effects and values into one thing, fork can return any result from the constructor synchronously, giving you a nice place to return controls over the eventual effect (for some implementations, this is where a cancelation control is returned)
Keith Alexander
@kwijibo
Feb 14 2017 21:59
https://goo.gl/R9Rs08 functional implementation of Task - Task.map(f)(fork) takes a fork function and an unary function, and returns the composed function