These are chat archives for ramda/ramda

24th
Sep 2015
hemanth.hm
@hemanth
Sep 24 2015 08:20
heh heh interesting title ^
Martin Algesten
@algesten
Sep 24 2015 08:51
a while back I tried to do "functional views". web views, like backbone or ember but functions. now I'm looking at revising the API and it's pretty much built like one big side effect - functions without return values. could anyone give me a pointer to how to think functionally about that problem. I.e function returns something and this something is in some way updating a DOM state.
I guess updating a DOM state is always a side effect?
Ludwig Magnusson
@TheLudd
Sep 24 2015 08:58
Yes updating the dom is a side effect.
In react you do it by setting state on an object component.setState(newState). This does not return anything so it is considered a side effect. If you want to go functional on it I do beleive the IO monad is the answer
Martin Algesten
@algesten
Sep 24 2015 09:12
ok. i look at the IO monad.
Martin Algesten
@algesten
Sep 24 2015 09:46
this one is really good explanation of monads. http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html i feel like redoing it with javascript-syntax.
Mark Perry
@mperry
Sep 24 2015 09:46
I think you need the ST monad for mutable state. See https://en.wikibooks.org/wiki/Haskell/Mutable_objects and http://blog.jakubarnold.cz/2014/07/20/mutable-state-in-haskell.html for some details (amongst others).
Rather than IO where we are updating a variable.
Martin Algesten
@algesten
Sep 24 2015 09:47
thanks @mperry! who knew today would be a study of monads :)
Mark Perry
@mperry
Sep 24 2015 10:01
@algesten That post is great. It really helped me when I first started on this topic.
Martin Algesten
@algesten
Sep 24 2015 10:02
yes. @mperry the functor, applicative and monad as 1-2-3. i never got that before.
Dave Keen
@ccapndave
Sep 24 2015 10:56
Hey Ramdaers
How would I write this using only Ramda functions? R.reduce((acc: Unit[], course: Course) => acc.concat(course.units), []),
Martin Algesten
@algesten
Sep 24 2015 10:57
isn't this just a map?
Dave Keen
@ccapndave
Sep 24 2015 10:58
No, it goes over a list of courses (each of which contain a units list) and you end up with a flat list of all the units
Martin Algesten
@algesten
Sep 24 2015 10:59
R.flatten + R.map then?
Dave Keen
@ccapndave
Sep 24 2015 10:59
Huh
Martin Algesten
@algesten
Sep 24 2015 11:00
So. R.map to get something that looks like [[unit1, unit2], [unit3, unit4]]
Dave Keen
@ccapndave
Sep 24 2015 11:00
By jove
Martin Algesten
@algesten
Sep 24 2015 11:00
and then R.flatten that to [unit1, unit2, unit3, unit4]
Dave Keen
@ccapndave
Sep 24 2015 11:00
You are right
Martin Algesten
@algesten
Sep 24 2015 11:00
:)
Dave Keen
@ccapndave
Sep 24 2015 11:00
Its a flatMap
Do we have that in Ramda?
Martin Algesten
@algesten
Sep 24 2015 11:00
we have flatten and map ;)
Dave Keen
@ccapndave
Sep 24 2015 11:01
Fair enough
Thanks a lot! I need to go and rewrite half my code now
Martin Algesten
@algesten
Sep 24 2015 11:02
hehe
Dave Keen
@ccapndave
Sep 24 2015 11:02
I knew it was wrong :)
R.pipe(R.pluck('units'), R.flatten)(courses)
Like that?
Martin Algesten
@algesten
Sep 24 2015 11:03
that would work
Dave Keen
@ccapndave
Sep 24 2015 11:03
Awesome
Thanks again
Martin Algesten
@algesten
Sep 24 2015 11:03
hm. would that work.
you need a map since you have a list.
R.pluck works on an object. not a list of objects.
R.pipe(R.map(R.pluck('units')), R.flatten)(courses)
Dave Keen
@ccapndave
Sep 24 2015 11:04
No, pluck works on a list
Martin Algesten
@algesten
Sep 24 2015 11:04
:o
yes.
sorry. ignore me :)
Dave Keen
@ccapndave
Sep 24 2015 11:05
No worries :)
Its all extremely confusing
I wonder why there isn't a flatMap alias in Ramda. Its a pretty mainstream functional tool
ramda/ramda#1403
Martin Algesten
@algesten
Sep 24 2015 11:09
it's called R.chain apparently http://ramdajs.com/0.17/docs/#chain
Mark Perry
@mperry
Sep 24 2015 11:09
Rambda uses the term 'chain' instead of flatMap.
I don't know why chain is used or it's history
Martin Algesten
@algesten
Sep 24 2015 11:10
perhaps flatMap as a term can be confused with handling monads? since ramda is not doing all fantasy-land stuff?
Dave Keen
@ccapndave
Sep 24 2015 11:11
I think its more confusing to come up with a new name
List is a monad, anyway
Ludwig Magnusson
@TheLudd
Sep 24 2015 11:33
@mperry I don't beleive that the fact that the react library has a method called setState is cause to use the State monad. They also have a method called setProps which does similair things. The point is that those methods are the end of purity and beginning of side effects.
Martin Algesten
@algesten
Sep 24 2015 11:38
@TheLudd there may be another concern which means the state-monad could be more appropriate (i don't know). i use virtual-dom which means i maintain a DOM-state. render a new state and does a diff between the two. the diff is applied to the actual DOM. now this is all the end of purity. but it may be that the current virtual-dom state should sit well in an ST monad.
Ludwig Magnusson
@TheLudd
Sep 24 2015 11:39
Well, all of that dom rendering and diffing is outside my code. If you were to implement that (which libraries like react does) then you might find use of the State monad, yes
Martin Algesten
@algesten
Sep 24 2015 11:40
what i do is like react, but trying to be more functional friendly.
Dave Keen
@ccapndave
Sep 24 2015 11:42
@algesten That's what I am doing too. I keep meaning to try redux-rx for smart components, but haven't managed yet
Ludwig Magnusson
@TheLudd
Sep 24 2015 11:43
Are you writing an entire dom-rendering library?
Dave Keen
@ccapndave
Sep 24 2015 11:43
virtual-dom is already a dom-rendering library
Ludwig Magnusson
@TheLudd
Sep 24 2015 11:43
There is this module on npm wich aims to let one use react in a "functional" manner https://www.npmjs.com/package/functional-react
Martin Algesten
@algesten
Sep 24 2015 11:50
i use virtual-dom
not a big fan of react
Scott Sauyet
@CrossEye
Sep 24 2015 12:05
We use chain instead of flatMap trying to keep with the Fantasy-land spec. By doing this, and by doing our dispatching, Ramda should appropriately call any Fantasy-land Monad.
Martin Algesten
@algesten
Sep 24 2015 12:06
@CrossEye thanks!
Raine Virta
@raine
Sep 24 2015 12:06
re: aliases, in my opinion they're an insane thing to have in a library. I think people find them acceptable because the most popular library, lodash, has a ton of them. what if javascript had both methods .filter and .select in arrays, nonsense
Martin Algesten
@algesten
Sep 24 2015 12:07
@raine what about functions that are rather simple composables. like R.pluck?
Scott Sauyet
@CrossEye
Sep 24 2015 12:08
I was reluctant to give them up, but I'm glad we did.
I still miss reduce -> fold and identity -> I.
Martin Algesten
@algesten
Sep 24 2015 12:10
why did you rename fold and I?
Scott Sauyet
@CrossEye
Sep 24 2015 12:10
@algesten: I for one distinguish syntactic sugar from aliases.
We had both reduce and fold as aliases. When we removed aliases, we had to choose. We actually choose fold then viewed to the outcry.
Bowed to the outcry
Martin Algesten
@algesten
Sep 24 2015 12:13
haha :D
Scott Sauyet
@CrossEye
Sep 24 2015 12:13
Damn auto-correct.
Raine Virta
@raine
Sep 24 2015 12:13
I guess the reason was also consistency with JS method names
other ones were aligned with JS names, then suddenly fold and foldr
Scott Sauyet
@CrossEye
Sep 24 2015 12:14
Yes, and to a user-base that had already chosen.
When they were aliases, it wasn't as issue.
Martin Algesten
@algesten
Sep 24 2015 12:14
i simply want to write less. so fold > reduce and I > identity
Scott Sauyet
@CrossEye
Sep 24 2015 12:14
But there were good reasons to remove the aliases.
Martin Algesten
@algesten
Sep 24 2015 12:15
and i understand "folding" better as a metafor for what is going on.
reduce is a bit more imperative. it's like we ought to have an accumulator in there when we are reducing.
Scott Sauyet
@CrossEye
Sep 24 2015 12:15
I feel that way about I. fold is more complicated.
Right
Martin Algesten
@algesten
Sep 24 2015 12:17
first time i saw R.pipe or composing done as a reduce I was like jumping off my chair in excitement. :)
Raine Virta
@raine
Sep 24 2015 12:17
again, IMO, if someone wants to alias identity to I, they are free to do that in their code. but the whole "ecosystem" should not be polluted with code that has multiple names for the same thing
Scott Sauyet
@CrossEye
Sep 24 2015 12:18
Same feeling @algesten!
Raine Virta
@raine
Sep 24 2015 12:19

ramda-cli has aliased R.identity to id.

cat data.json | R id is a very common thing to do, and R I looks weird

Scott Sauyet
@CrossEye
Sep 24 2015 12:19
oh look, there's a whole issue dedicated to flatMap / chain. Guess I should have read that first. :smile:
Julien Goux
@jgoux
Sep 24 2015 13:14
Hi
Is there an easy way to rename object's keys with ramda ?
Raine Virta
@raine
Sep 24 2015 13:15
jgoux: in what way?
Julien Goux
@jgoux
Sep 24 2015 13:20
It'll do ! Thanks :D
Martin Algesten
@algesten
Sep 24 2015 16:49
so. i have an array of functions [fn1, fn2, fn3]. and now i want to apply each to the same object and end up with an array of the results [fn1(o), fn2(o), fn3(o)]
is there such a function?
Aldwin Vlasblom
@Avaq
Sep 24 2015 17:08
@algesten R.ap? Seems like all you need to do is wrap the object in an array.
Martin Algesten
@algesten
Sep 24 2015 17:12
oh yes. look at that!
joneshf-work1
@joneshf-work1
Sep 24 2015 17:19
R.map(function(f) { return f(obj); }, funcs)
or somethign
Martin Algesten
@algesten
Sep 24 2015 17:20
haaaang on. my head is spinning :)
ah ok. yes we need to inject obj then.
function(obj) { return R.map(function(f) { return f(obj); }, funcs) }
joneshf-work1
@joneshf-work1
Sep 24 2015 17:23
probably also
R.map(R.call(R.__, obj), funcs)
Martin Algesten
@algesten
Sep 24 2015 17:24
oh that's sweet
Caleb Gossler
@itscaleb
Sep 24 2015 18:02

Beginner here. Is there a way to do something like:

Either.of(add).ap(Either.of(5)).ap(Either.Left(2));

The second value I want to add is a Left, although not an entirely unexpected result so I still want to add them together. But of course in this case it will result in a Left containing a 2.

David Chambers
@davidchambers
Sep 24 2015 18:04
Why must you add a Left and a Right?
Caleb Gossler
@itscaleb
Sep 24 2015 18:10
I guess it's a bad example, but say a function has two parameters, and the function has a check if one of the params is invalid?
in my case i'm making two requests to an API and i want to apply a function to them
but if one of the requests fails, I don't want the function to fail, i want to handle one of the failures and return a result.
David Chambers
@davidchambers
Sep 24 2015 18:12
Do you mean you want to try two operations which may fail and choose a successful result?
joneshf-work1
@joneshf-work1
Sep 24 2015 18:13
@itscaleb it sounds like whatever is doing the requests is returning the wrong value.
@itscaleb if the "failure" isn't actually a failure, it should still return a "successful" value, right?
that doens't mean you need to go in and alter the inner workings of the requesting function.
Caleb Gossler
@itscaleb
Sep 24 2015 18:15
I want to do some processing on the results of two futures, but for various reasons there could be a failure in getting one of the results. Maybe network or something
joneshf-work1
@joneshf-work1
Sep 24 2015 18:15
but you can wrap whatever is calling it in a call to getOrElse or whatever it is.
or #either
right.
Caleb Gossler
@itscaleb
Sep 24 2015 18:18
I'll think about the getOrElse approach. Thanks.
David Chambers
@davidchambers
Sep 24 2015 18:20
You could use S.or or a similar function provided by another library:
> S.or(S.Left('Error!'), S.Left('Oh noes!'))
Left("Oh noes!")
> S.or(S.Left('Error!'), S.Right(42))
Right(42)
> S.or(S.Right(42), S.Left('Error!'))
Right(42)
> S.or(S.Right(42), S.Right(99))
Right(42)
Caleb Gossler
@itscaleb
Sep 24 2015 18:22

I might just not be thinking about this correctly. But the type of function I'm thinking about is something like:

function process(arg1, arg2) {
  if(!arg2) {
    return result1; 
  }
  return result2;
}

but arg1 and arg2 could be a Maybe, Either, or Future. Maybe.of(process).ap(arg1).ap(arg2)

thanks @davidchambers, I'll look into that as well
Ludwig Magnusson
@TheLudd
Sep 24 2015 18:24
@itscaleb
lift2(defaultTo)?
Caleb Gossler
@itscaleb
Sep 24 2015 18:26
@TheLudd that looks promising, I'll give that a try too!
Ludwig Magnusson
@TheLudd
Sep 24 2015 18:27
lift2 and lift3 in ramda-fantasy are not mentioned in the readme but they are there. Perhaps ramdas lift will also work...
I have never seen someone talk about monads before and call themselves "a beginner" :)
Caleb Gossler
@itscaleb
Sep 24 2015 18:27
oh nice.
Jethro Larson
@jethrolarson
Sep 24 2015 18:29
Monads for Dummies
Caleb Gossler
@itscaleb
Sep 24 2015 18:29
Haha. I've been fighting through this stuff the past couple weeks and lurking on here, but very much in the beginner stage. Tired of working in nasty JS code and would like to start off a new project on a solid foundation.
Jethro Larson
@jethrolarson
Sep 24 2015 18:30
I think we're all still figuring it out!
Caleb Gossler
@itscaleb
Sep 24 2015 18:32
thanks everyone for the suggestions.
joneshf-work1
@joneshf-work1
Sep 24 2015 19:23
@itscaleb the idea is that your "add" function there shouldn't worry about the logic behind good or bad requests, it should just add two Rights or bail early for Lefts
yeah, I know it was just an example, but similar points apply to your actual function.
but like @TheLudd said, you really want lift2(add) or whatever your function was.
If you want a network error not to propagate, it's usually better to stop it where you want the propagation to stop, not wait until the end of the line and handle that logic there.
you can use or like @davidchambers suggested, that's probably the cleanest way.
Caleb Gossler
@itscaleb
Sep 24 2015 19:32
@joneshf-work1 yeah, that makes a lot of sense. I'll let these ideas bake for a while and give it another try.