These are chat archives for ramda/ramda

25th
Mar 2016
joneshf-work1
@joneshf-work1
Mar 25 2016 02:15
hmm
do traversals work properly with lenses?
Scott Christopher
@scott-christopher
Mar 25 2016 04:40
@joneshf-work1 kinda
the main problem is ap isn't implemented for the Identity and Const inside over and view
then the other annoyance is having to specify the of function for the first arg to traverse
Which obviously changes depending on whether you end up using view or over
But if you address those, they do work as expected.
Jonah
@jonahx
Mar 25 2016 04:47
@joneshf-work1 I’m messing around with pg-promise, and getting an error on db.query("select * from campuses”): 'db.query is not a function’. any ideas what’s wrong?
Jonah
@jonahx
Mar 25 2016 05:06
nm, you have to manually tell it which promise lib to use...
Hardy Jones
@joneshf
Mar 25 2016 12:16
@scott-christopher interesting
Julien Goux
@jgoux
Mar 25 2016 13:06
Hi
Is there a function in ramda to apply a list of function to a list of elements, then return the list of results ?
//:: [f, g] -> [a, b] -> [f(a), g(b)]
something like that
James Forbes
@JAForbes
Mar 25 2016 13:07
ap?
R.ap([R.multiply(2), R.add(3)], [1,2,3]); //=> [2, 4, 6, 4, 5, 6]
except with ap you'l get [f(a), f(b), g(a), g(b)]
Julien Goux
@jgoux
Mar 25 2016 13:10
it's close but I don't think it's what I want sorry ^^
James Forbes
@JAForbes
Mar 25 2016 13:11
maybe juxt composed with apply?
Denis Stoyanov
@xgrommx
Mar 25 2016 13:23
@jgoux R.zipWith(R.call, [R.add(2), R.multiply(3)], [2,3]);
@ram-bot R.zipWith(R.call, [R.add(2), R.multiply(3)], [2,3])
ram-bot
@ram-bot
Mar 25 2016 13:23
[ 4, 9 ]
Julien Goux
@jgoux
Mar 25 2016 13:24
@xgrommx niceee !
:+1:
Do you know if there is a name for this ?
R.zipWith(R.call)
Denis Stoyanov
@xgrommx
Mar 25 2016 13:25
no
but maybe I can be wrong
Julien Goux
@jgoux
Mar 25 2016 13:26
I'll ping people on Haskell irc to ask
thank you !
Denis Stoyanov
@xgrommx
Mar 25 2016 13:35
@jgoux another ugly solution R.useWith(R.unapply(R.identity), [R.add(10), R.multiply(2)])(...[1, 2])
@ram-bot R.useWith(R.unapply(R.identity), [R.add(10), R.multiply(2)])(...[1, 2])
ram-bot
@ram-bot
Mar 25 2016 13:36
[ 11, 4 ]
Julien Goux
@jgoux
Mar 25 2016 13:36
I think the first one is definitly what I want :D
Plus, I wouldn't need to generalize it to lists, because I'll only work on pairs
[a, b] -> [f, g] -> [f(a), g(b)]
maybe I can look at pairs functions
Hardy Jones
@joneshf
Mar 25 2016 14:04
@jgoux if you change your data types, then ap can work.
Hardy Jones
@joneshf
Mar 25 2016 14:10
There is more than one lawful Apply implementation for the array data type. The default one operates on all combinations. But there's another one that operates pair-wise.
Walle Cyril
@GrosSacASac
Mar 25 2016 14:18
@Risto-Stevcev added a playground http://jsbin.com/migeya/4/edit?html,js,output
Hardy Jones
@joneshf
Mar 25 2016 14:35
@jgoux I realize that was pretty vague.
@ram-bot
const ZipArray = xs => ({
  map: f => ZipArray(xs.map(f)),
  ap: ys => ZipArray(
    R.range(0, R.min(xs.length, ys.length)).map(i => xs[i](ys.runZipArray[i]))
  ),
  runZipArray: xs,
  inspect: () => `ZipArray([${xs}])`,
});

R.ap(ZipArray([R.multiply(2), R.add(3)]), ZipArray([2, 3]));
ram-bot
@ram-bot
Mar 25 2016 14:36
ZipArray([4,6])
Hardy Jones
@joneshf
Mar 25 2016 14:36
in fact...
Hardy Jones
@joneshf
Mar 25 2016 14:46
wait, that shouldn't work...
ys.length should be undefined...
Julien Goux
@jgoux
Mar 25 2016 15:05
I don't understand, why do you create an object ?
John-David Dalton
@jdalton
Mar 25 2016 15:27

@boxofrox It's based on set theory. See MDN Array#every:

every acts like the "for all" quantifier in mathematics. In particular, for an empty array, it returns true.
(It is vacuously true that all elements of the empty set satisfy any given condition.)

Hardy Jones
@joneshf
Mar 25 2016 15:40
Also, I feel like every and some are so underused.
I don't think many people know they even exist.
I only recently found out.
@jgoux Each data type can only have one implementation of Apply (assuming it can lawfully implement it). Since the common Apply instance does combinations, we need a different data type to implement the Apply which does "pairwise" stuff.
Denis Stoyanov
@xgrommx
Mar 25 2016 15:42
Hardy Jones
@joneshf
Mar 25 2016 15:42
@xgrommx I know, right?
@xgrommx unbelieveable that it's been around so long, but rarely is talked about or used.
Denis Stoyanov
@xgrommx
Mar 25 2016 15:43
:+1:
Julien Goux
@jgoux
Mar 25 2016 15:44
ok, thanks @joneshf for the explanation !
Denis Stoyanov
@xgrommx
Mar 25 2016 15:46
@joneshf @jgoux why not smth like http://ramdajs.com/docs/#traverse
also we can use Ramda with http://sanctuary.js.org/ togeher
Brad Compton (he/him)
@Bradcomp
Mar 25 2016 15:49
@joneshf :+1:
Denis Stoyanov
@xgrommx
Mar 25 2016 15:51
do u like one line code?))) I love do it const zip = (...xs) => [...Array(Math.min(...xs.map(x => x.length)))].map((_, i) => xs.map(x => x[i]))
const zipWith = (fn, ...xs) => zip(...xs).map(x => fn(...x));
Hardy Jones
@joneshf
Mar 25 2016 15:53
traverse solves a different problem.
well, that's not entirely true
but pulling out that abstraction leads to interesting results.
GÁBOR Áron Zsolt
@ashnur
Mar 25 2016 15:54
@joneshf it's not just that they don't know about every,some or even filter,map,reduce and they are instead reimplementing the logic of these every time they need it (using nested ifs and loops), but when you go and show them that look, your 50 line of code is now a 5 line function and 2 lines of code, why not do it like this, they say "it's not my style of coding, this is a stylistic choice" And I am not talking figuratively, this happened to me less than a year ago.
Hardy Jones
@joneshf
Mar 25 2016 15:56

I don't have the time to implement the Applicative implementation in js right now, but in haskell you can do this with sequence:

λ: sequenceA (ZipList [ZipList [1,2,3], ZipList [4,5,6], ZipList [7,8,9]])
ZipList {getZipList = [ZipList {getZipList = [1,4,7]},ZipList {getZipList = [2,5,8]},ZipList {getZipList = [3,6,9]}]}

So you get transpose for free, just by changing your Apply implementation to more closely match your intentions.

syntax aside, you're calling sequence on a ZipList (ZipList a), and it transposes the elements, rather than if you called sequence on [[a]], you could get all combinations of the elements.
@ashnur yeah, that's a real problem.
Hardy Jones
@joneshf
Mar 25 2016 16:01
@jgoux that's the real answer, I suppose. ziparray is a cute trick when you need to apply an array of functions to an array of values, though cumbersome due to wrapping/unwrapping. But the real benefit comes when you use other functions that work off of its Apply effects.
Aldwin Vlasblom
@Avaq
Mar 25 2016 17:05
Is there a function in Ramda for finding the overlapping elements in two lists?
Aldwin Vlasblom
@Avaq
Mar 25 2016 17:06
Ah yes. I knew I saw it before but it took forever to find. :) Thanks.
Julien Goux
@jgoux
Mar 25 2016 17:07
I thought about INTERSECT in SQL xD
Aldwin Vlasblom
@Avaq
Mar 25 2016 17:08
I was lost for the word. It happens to me a lot. Words are hard.
Chet Harrison
@ChetHarrison
Mar 25 2016 22:37
Does "replace" return a new instance of the string?
Scott Sauyet
@CrossEye
Mar 25 2016 22:38
Yes
Aldwin Vlasblom
@Avaq
Mar 25 2016 22:38
Strings in JavaScript are immutable.
Chet Harrison
@ChetHarrison
Mar 25 2016 22:39
so if I just use the native JS replace I get a new string
thx
Jonah
@jonahx
Mar 25 2016 22:54

What is the best way (I assume using monads, somehow) to write callback/promise code without callbacks, as if were just syncronous. eg, consider this DB interaction:

  db.query("select * from campuses")
  .then(function (data) {
    resp.body = data;
    resp.status = 200;
  })

I’d much rather think of it as data = db.query("select * from campuses”). Thoughts? Advice?

James Forbes
@JAForbes
Mar 25 2016 22:59

It depends what you want to do with the response. In some cases you can get very sync looking code.

var campuses = db.query('select * from campuses')

//assuming bluebird promise
var campus_names = R.map(R.prop('campus_name'), campuses)

var capitalized = R.map(R.toUpper, campus_names)

Because ramda often dispatches to underlying methods then you can get the sync feel even though at every stage there, each variable is a promise.

In your example though, you'd probably need a callback.

Another thing to consider is using composition.

var async = callback=> promise => promise.then(callback)

var endpoint = R.pipe(
  _ => db.query('select * from campuses'),
   R.map(R.prop('campus_name'),
   R.map(R.toUpper),
   async(
      data => {
         response.body = data
         response.status = 200
      }
   )
)

endpoint()

In the above, the R.map doesn't need the async modifier because it dispatches to Promise.map. You can then use async (defined above) to do some imperative code

Both of my suggestions ignore using Futures/etc. I just thought I'd point out that promises do return values synchronously, its just not the value you want.
James Forbes
@JAForbes
Mar 25 2016 23:07
Note the code above would work exactly the same way (except for the async call) if it was an array or a future or some other datatype that has .map implemented correctly.