@buzzdecafe That's cool. I've never seen Black Box before. But it looks like something that could be a lot of fun for a clever child (or grown up) :smile:

Can someone tell me how ap works?

R.ap([R.multiply(2), R.add(3)], [1,2,3]); //=> [2, 4, 6, 4, 5, 6]

R.ap([R.concat('tasty '), R.toUpper], ['pizza', 'salad']); //=> ["tasty pizza", "tasty salad", "PIZZA", "SALAD"]

R.ap([R.concat('tasty '), R.toUpper], ['pizza', 'salad']); //=> ["tasty pizza", "tasty salad", "PIZZA", "SALAD"]

This is from ramda documentation

I understand it applies the list of functions to a data set

but how did the results of each function application is concatenated

and how's it different from converge

@IsaacRaja_twitter

I've got this same thoughts. (I am not ramda expert so I may be wrong)

converge -> Imho its usefull that you need to apply functions and then merge results of this functions together. Example: calculating avg score. First argument to converge is function which will 'merge/connect' result of the array of function passed in 2nd argument. `R.converge(R.divide, [R.sum, R.length]) .`

So first step is that you got result from sum and length, and its passed to 'merge' function -> and the end you finish with ONE result

AP is different -> Firstly you will not end with one result, but an array. and as you have mention it just apply functions on a data set.. And its JUST concatenated,

R.ap([R.multiply(2), R.add(3)], [1,2,3]); First step apply R.multiply, and you get [2,4,6], 2nd step [4,5,6], concatenate and you got final result [2,4,6,4,5,6]

Of course you can also write AP, using converage with 'merge' function set to 'contact'

`R.converge(R.concat, [R.map(R.multiply(2)), R.map(R.add(3))])([1,2,3])`

For me converge is like 'splitting' value to two functions, do some calculations, and merge them back (I've noticed its usefull for point free, if you need to get the argument in two or more places)

@mimol91 Thanks! It clears up a bit. But then

`const isPalindrome = R.ap(R.equals, R.reverse)('test')`

i don't understand how this works
Hey guys, it’s there a better way (in terms of readability) to ge the minumum of a list based on minBy?

I remember a issue minListBy, but didn’t progress

any ideas?

@IsaacRaja_twitter Dont worry for me also

`const isPalindrome = s => s === R.reverse(s)`

is much easier to understand
@svozza Could you explain how does this palindrome works? Unfortunatelly ramda doc has all examples with an array as argument

yeah, no problem. if you look in the docs it contains the cryptic sentence

`Also treats curried functions as applicatives.`

what that means in reality is that when you pass two functions to

`ap`

rather than arrays they get treated like this:`const h = f => g => x => f(x, g(x));`

the tests in ramda are very instructive

so

`R.ap(R.equals, R.reverse) === x => R.equals(x, R.reverse(x))`

hmm, my mind is blowing...

is it possible to force converge to works on single value instead of array

How can I make it to be equal?

is it possible to force converge to works on single value instead of array

How can I make it to be equal?

`R.converge(R.add, [R.idenity, R.idenity])(10) === R.ap(R.add, R.identity)(10)`

so like?

`const palindrome = R.converge(R.equals, [R.identity, R.reverse])`

oh sorry, i misunderstood your question

your example works, although you have a typo in

`R.idenTity`

@ram-bot

`R.converge(R.add, [R.identity, R.identity])(10)`

`20`

@ram-bot

`R.ap(R.add, R.identity)(10)`

`20`

ahh,, thanks

I like, that almost everyday I m learning sth new here =)

actually that's a good way of thinking about it if you're used to using converge. Any time you find yourself writing

`R.converge(f, [R.identity, g])`

you can use `ap`

Does anyone use Typescript with Ramda? Is there a way to typecheck the 'thing' field in

`R.prop('thing', a)`

?
I think @tycho01 is the person here with the most experience with Ramda and Typescript