These are chat archives for ramda/ramda

27th
Oct 2015
Asaf
@asaf-romano
Oct 27 2015 04:58
@CrossEye Is ramda/ramda#1466 something that you'd considering taking a fix for? I know it happened intentionally (as part of that |lift| work)
I had to change few use cases of both to allPass for now.
Scott Christopher
@scott-christopher
Oct 27 2015 08:51
Just discovered a neat trick now that ap supports the applicative behaviour of functions.
var juxt = R.commute(R.always);
var addSubtract10 = juxt([R.add(10), R.subtract(10)])
addSubtract10(5); //=> [15, 5]
Denis Stoyanov
@xgrommx
Oct 27 2015 08:58
@scott-christopher Why not R.converge(R.unapply(R.identity), [R.add(10), R.subtract(10)])(5) ?
Scott Christopher
@scott-christopher
Oct 27 2015 08:59
That was what I first reached for.
Denis Stoyanov
@xgrommx
Oct 27 2015 09:01
With ap => R.pipe(R.unapply(R.identity), R.ap([R.add(10), R.subtract(10)]))(5)
Scott Christopher
@scott-christopher
Oct 27 2015 09:02
You could also swap the R.unapply(R.identity) with R.of in that instance.
Denis Stoyanov
@xgrommx
Oct 27 2015 09:03
@scott-christopher what do u mean?
Scott Christopher
@scott-christopher
Oct 27 2015 09:04
R.pipe(R.of, R.ap([R.add(10), R.subtract(10)]))(5)
Denis Stoyanov
@xgrommx
Oct 27 2015 09:04
@scott-christopher yes it's more simply
Tobias Pflug
@gilligan
Oct 27 2015 09:05
neat ;)
@scott-christopher want to add that to the ramda cookbook page ?
Scott Christopher
@scott-christopher
Oct 27 2015 09:06
Sure, I can throw something up.
Raine Virta
@raine
Oct 27 2015 09:07
bonus points rewarded for explaining how it works
Scott Christopher
@scott-christopher
Oct 27 2015 09:08
@raine the commute example?
Raine Virta
@raine
Oct 27 2015 09:08
yep
Tobias Pflug
@gilligan
Oct 27 2015 09:09
i would only add the pipe one, the commute one looks kinda meh ;-)
Raine Virta
@raine
Oct 27 2015 09:09
the ap pattern I've used before
Scott Christopher
@scott-christopher
Oct 27 2015 09:09
Alright, here goes :P
Denis Stoyanov
@xgrommx
Oct 27 2015 09:10
http://ramdajs.com/0.18.0/docs/#commute - An array of functors of the same type (if this functor like a function)
Scott Christopher
@scott-christopher
Oct 27 2015 09:11
commute takes a list (or potentially any traversable - see #1467) of applicative functors containing some value a, and effectively inverts it to become an applicative functor of a list as.
Denis Stoyanov
@xgrommx
Oct 27 2015 09:12
Looks like commute like a converge?
Scott Christopher
@scott-christopher
Oct 27 2015 09:14
Focussing on arrays as the traversable (the default provided by ramda), it starts by creating a pure applicative instance of an empty array.
Denis Stoyanov
@xgrommx
Oct 27 2015 09:14
var juxt = R.converge(R.unapply(R.identity));
var addSubtract10 = juxt([R.add(10), R.subtract(10)])
addSubtract10(5); //=> [15, 5]
Scott Christopher
@scott-christopher
Oct 27 2015 09:15
It then works from the right to the left of the list, prepending each value via ap.
So to use a concrete example of Maybe as the applicative.
var just123 = [Just(1), Just(2), Just(3)];
R.commute(Maybe.of, just123); //=> Just([1, 2, 3]);
Scott Christopher
@scott-christopher
Oct 27 2015 09:17
var maybe123 = [Just(1), Nothing, Just(3)];
R.commute(Maybe.of, maybe123); //=> Nothing
Denis Stoyanov
@xgrommx
Oct 27 2015 09:19
@scott-christopher this example can be reproduced with converge?
Raine Virta
@raine
Oct 27 2015 09:20
@scott-christopher if it was haskell (and we had type inference), would we need the first argument to commute?
Scott Christopher
@scott-christopher
Oct 27 2015 09:21
commute effectively performs the following steps:
var _0 = Maybe.of([]); //=> Just([])
var _1 = ap(map(prepend, Just(3)), Just([])); //=> Just([3]);
var _2 = ap(map(prepend, Nothing), Just([3])); //=> Nothing;
var _3 = ap(map(prepend, Just(1)), Nothing); //=> Nothing;
Or:
var _0 = Maybe.of([]); //=> Just([])
var _1 = ap(map(prepend, Just(3)), Just([])); //=> Just([3]);
var _2 = ap(map(prepend, Just(2)), Just([3])); //=> Just([2, 3]);
var _3 = ap(map(prepend, Just(1)), Just([2, 3])); //=> Just([1, 2, 3]);
@xgrommx: Which example in particular
@raine: that's correct, we only need to explicity pass the of here because we can't infer it
@raine If we were guaranteed a non-empty list, we could work it out from the head of the list, but we need it there in case an empty list is provided.
So, if you have a general understanding with the examples using Maybe above, we can swap out Maybe for plain JS functions as the applicative.
Denis Stoyanov
@xgrommx
Oct 27 2015 09:26
Will be better if we will have some lists with equivalents between ramda and haskell or ramda and clojurescript or ramda and lodash (latest is joke but why not :smile: )
Julien Goux
@jgoux
Oct 27 2015 09:29
Hello
Is there an easy way to get the index of the current object in R.map ?
Viktor Fröberg
@vikfroberg
Oct 27 2015 09:30
R.addIndex
Julien Goux
@jgoux
Oct 27 2015 09:30
return R.map(
            R.cond([
                [ R.propEq("type", "TILE_LAYER"), l => <TileLayer key={} {...l.options} /> ],
                [ R.T, () => {} ]
            ])
        )(layers)
Raine Virta
@raine
Oct 27 2015 09:30
search the docs of mapIndexed
Julien Goux
@jgoux
Oct 27 2015 09:30
I need the index for the key attribute :p
@raine There is no mapIndexed in the doc, for the version 0.18.0
Raine Virta
@raine
Oct 27 2015 09:31
I mean really search it, cmd-f or ctrl-f
Julien Goux
@jgoux
Oct 27 2015 09:32
sorry xD
I found it with the mapIndexed, thanks ! :D
addIndex*
thanks @vikfroberg too !
Scott Christopher
@scott-christopher
Oct 27 2015 09:34
The applicative behaviour of functions is more or less:
R.ap(fn1, fn2) == x => fn1(x)(fn2(x)
Function.of == R.always // (if Function.of were a thing)
Raine Virta
@raine
Oct 27 2015 09:37
should > ap(add, add(1))(1) work?
add(1)(add(1)(1)) => 3
ap(add, add(1))(1) => Function
Scott Christopher
@scott-christopher
Oct 27 2015 09:49
This is where it gets a little mind bending, because the first argument to to ap must be an applicative that contains a function. So for functions, that would be a function that contains a function.
So if we treat R.always as a way to get a pure instance of something in the function applicative, we can do so like:
R.ap(R.always(R.add(4)), R.multiply(2))(3) // 3 * 2 + 4
Raine Virta
@raine
Oct 27 2015 09:55
makes sense
why doesn't R.of(R.add(1)) do R.always(add(1))?
Scott Christopher
@scott-christopher
Oct 27 2015 09:57
R.of will always produce the pure instance of an array, because we can't infer the type we want
Raine Virta
@raine
Oct 27 2015 09:57
does the behavior of R.of to wrap in list context regardless of type make sense?
Scott Christopher
@scott-christopher
Oct 27 2015 09:58
The argument to of will end up inside the applicative, rather than giving any indication as to which applicative we want returned. e.g. R.of(1) == [1]
Denis Stoyanov
@xgrommx
Oct 27 2015 10:00
It's more simply =) R.compose(R.add(4), R.multiply(2))(3)
Scott Christopher
@scott-christopher
Oct 27 2015 10:01
This, what I refer to as "return type inference", is the thing that gets in the way of a lot of nice things other languages with a static type system can do that we can't do in JS, which is why we need to explicitly pass around things like the of parameter to commute.
@xgrommx: yeah, I wouldn't often suggest people reach for ap for functions :)
Scott Christopher
@scott-christopher
Oct 27 2015 10:06
You can also effectively implement converge using lift, to apply it over functions.
R.lift(R.add)(R.multiply(2), R.subtract(2))(4); // 6
// which roughly translates to
R.ap(R.map(R.add, R.multiply(2)), R.subtract(2))(4); // 6
And this is now starting to hurt my head, so I'm off to catch up on The Walking Dead :D
Have a good morning/day/evening all. :wave:
Raine Virta
@raine
Oct 27 2015 10:09
@scott-christopher cheers
I started watching the series last week
Scott Christopher
@scott-christopher
Oct 27 2015 10:10
It took some effort to avoid the spoilers from the most recent episode.
Denis Stoyanov
@xgrommx
Oct 27 2015 10:20
@scott-christopher lift is like a compose?
Denis Stoyanov
@xgrommx
Oct 27 2015 10:26
How can be used this example with curry? R.lift(R.add)(R.multiply(2), R.subtract(2))(4);
Scott Christopher
@scott-christopher
Oct 27 2015 10:39
@xgrommx lift converts a plain function to one that accepts applicative functors as arguments and then behaves according to the behaviour of the applicative.
Scott Christopher
@scott-christopher
Oct 27 2015 10:45
```js
Is there a trick to getting multi line input for gitter on iOS?
var addA = R.lift(R.add)
addA([1,10],[100,1000]) // [101, 1001, 110, 1010]
addA(Just(1), Just(2)) // Just(3)
addA(Nothing, Just(2))
Scott Christopher
@scott-christopher
Oct 27 2015 10:51
old man yells at gitter
Denis Stoyanov
@xgrommx
Oct 27 2015 11:06
Oh! [1 + 100, 1 + 1000, 10 + 100, 10 + 1000]; it's iterate by second array for each item of first array
Martin Algesten
@algesten
Oct 27 2015 11:16
@scott-christopher start with ``` then shift-return
Raine Virta
@raine
Oct 27 2015 11:17
on iOS?
Martin Algesten
@algesten
Oct 27 2015 11:18
uhm...
sorry. i'm confused.
On iOS
yes. same
shift-return
Raine Virta
@raine
Oct 27 2015 11:19
good to know, I've have trouble on iOS as well
Scott Christopher
@scott-christopher
Oct 27 2015 11:19
so
It
Does
Work
Thanks @algesten
Frederik Krautwald
@Frikki
Oct 27 2015 11:26
@scott-christopher You can also switch between compose mode and chat mode.
Raine Virta
@raine
Oct 27 2015 11:26
I'm relaying all gitter warts mentioned here to gitterHQ/gitter. hopefully in time it will get better
Raine Virta
@raine
Oct 27 2015 11:28
@Frikki we're talking about iOS
Frederik Krautwald
@Frikki
Oct 27 2015 11:29
@raine And? iOS Gitter doesn’t have compose mode?
Raine Virta
@raine
Oct 27 2015 11:29
I don't see that button
Frederik Krautwald
@Frikki
Oct 27 2015 11:37
@raine That’s strange. Try to ask in the gitterHQ/gitter room.
Julien Goux
@jgoux
Oct 27 2015 13:31
Is there an upsert like method in Ramda ?
I want to append or create an object in a list based on a function to identity the object
merge is for object
Hardy Jones
@joneshf
Oct 27 2015 13:53
upsert?
oh, it's a portmanteau.
Hardy Jones
@joneshf
Oct 27 2015 13:58
you probably want to help push this through: ramda/ramda#1443
Noam Lewis
@sinelaw
Oct 27 2015 17:52
hi
David Chambers
@davidchambers
Oct 27 2015 17:59
Hello, @sinelaw.
Noam Lewis
@sinelaw
Oct 27 2015 18:04
@davidchambers Hi! I heard you on that podcast this morning!
Ricardo Pallas
@RPallas92
Oct 27 2015 18:05
what podcast
Ricardo Pallas
@RPallas92
Oct 27 2015 18:06
thanks
Noam Lewis
@sinelaw
Oct 27 2015 18:06
@davidchambers Thanks for doing it, it was fun to listen to
joneshf-work1
@joneshf-work1
Oct 27 2015 18:08
@sinelaw hey
Noam Lewis
@sinelaw
Oct 27 2015 18:09
@joneshf-work1 Hello
David Chambers
@davidchambers
Oct 27 2015 18:09
I'm pleased you enjoyed it, @sinelaw. Nice to see you in the Gitter room. :)
joneshf-work1
@joneshf-work1
Oct 27 2015 18:10
How far away are we from having infernu installable from npm?
Noam Lewis
@sinelaw
Oct 27 2015 18:11
Every time you said we can't have type checking in that podcast, boosted my motivation a bit
@joneshf-work1 that's part of the reason I'm here: trying to figure out exactly what needs to be done
I mean getting it to be useable for stuff like Ramda
joneshf-work1
@joneshf-work1
Oct 27 2015 18:13
I think user definable type classes would be a big help.
Noam Lewis
@sinelaw
Oct 27 2015 18:15
there's this issue: sinelaw/infernu#27
I listed "optional arguments" as a thing, but maybe we don't need it?
David Chambers
@davidchambers
Oct 27 2015 18:16
No optional args in Ramda. :)
Noam Lewis
@sinelaw
Oct 27 2015 18:17
but there's arguments
I have a few ideas on how to support that, but it's better to work around it instead
David Chambers
@davidchambers
Oct 27 2015 18:19
We've been slowly replacing the variadic functions which take lists instead.
Noam Lewis
@sinelaw
Oct 27 2015 18:21
btw, why not IRC? a bit more reliable than gitter (it keeps dropping my messages)
David Chambers
@davidchambers
Oct 27 2015 18:22
In theory Gitter is the best of both worlds, since it talks IRC. In practice the iOS client in particular leaves a lot to be desired.
Noam Lewis
@sinelaw
Oct 27 2015 18:24
so, for low-level frameworky stuff that hacks around JS, such as _curry and friends, we can tell the checker what the type is and disable checking of the function body
Noam Lewis
@sinelaw
Oct 27 2015 18:37
ok, I'm back, using IRC this time
joneshf-work1
@joneshf-work1
Oct 27 2015 18:38
so are you looking to support all of how ramda is written (private api as well as public)? Or are you looking to support ramda's public api?
maybe support is the wrong word
Noam Lewis
@sinelaw
Oct 27 2015 18:39
I want to infer types for as much as possible, though I'm starting to think that for internal stuff that uses hacky arguments or optional params, it may be ok to have an 'unsafe' mode
so you could tell infernu the type of a function, and have it assume you're not lying
joneshf-work1
@joneshf-work1
Oct 27 2015 18:39
yeah, at least until it gets rolling.
Noam Lewis
@sinelaw
Oct 27 2015 18:40
so for that, I need to add type annotations
user-defined type classes are another story, shouldn't be hard to fix but not currently supported
joneshf-work1
@joneshf-work1
Oct 27 2015 18:45
I would assume those two would be the major blockers.
but others might know better
:)
as far as installing it from npm, any ideas there?
Noam Lewis
@sinelaw
Oct 27 2015 18:46
and 'requires()'
installing from npm - why is that important?
I mean, making it easy to install is
but why from npm?
joneshf-work1
@joneshf-work1
Oct 27 2015 18:47
adoption is tough when you tell people to install an additional language and package manager.
Noam Lewis
@sinelaw
Oct 27 2015 18:48
now that we have stack, it won't be a big deal
joneshf-work1
@joneshf-work1
Oct 27 2015 18:48
sure, no langauge, but still need the package manager.
Noam Lewis
@sinelaw
Oct 27 2015 18:49
ok, we can have an npm install script that installs stack and then installs infernu :)
my main problem with type annotations is that the next version of language-ecmascript isn't being released
joneshf-work1
@joneshf-work1
Oct 27 2015 18:52
oh?
Why is that a problem? I don't understand the context.
David Chambers
@davidchambers
Oct 27 2015 18:53
Is there a more precise word to describe a -> a -> a than "polymorphic"?
Noam Lewis
@sinelaw
Oct 27 2015 18:53
it's a haskell package I use to parse JS
davidchambers: in what context?
joneshf-work1
@joneshf-work1
Oct 27 2015 18:54
@sinelaw oh, I thought you meant the actual language. :)
Noam Lewis
@sinelaw
Oct 27 2015 18:54
ah, god forbid
David Chambers
@davidchambers
Oct 27 2015 18:55
I want to state that def('f', [a, a], f) produces a function which takes two arguments of any single type.
joneshf-work1
@joneshf-work1
Oct 27 2015 18:56
@sinelaw why isn't it being released?
David Chambers
@davidchambers
Oct 27 2015 18:56
Currently I'm saying 'supports polymorphism via type variables', but I wonder whether there should be an adjective before "polymorphism".
Noam Lewis
@sinelaw
Oct 27 2015 18:57
'a' is universally quantified, if you want to go there
saying that 'a' is "forall-ed" also works, or even "'a' is polymorphic"
why not just write the type signature a -> a -> a? says it all
David Chambers
@davidchambers
Oct 27 2015 18:59
I should provide more context:
it('supports polymorphism via type variables', function() {
  var aa = def('aa', [a, a], list);
  var ab = def('ab', [a, b], list);
  var abba = def('abba', [a, b, b, a], list);

  eq(aa(0, 1), [0, 1]);
  eq(aa(1, 0), [1, 0]);
  eq(ab(0, 1), [0, 1]);
  eq(ab(1, 0), [1, 0]);
  eq(ab(0, false), [0, false]);
  eq(ab(false, 0), [false, 0]);

  assert.throws(function() { aa(0, false); },
                errorEq(TypeError,
                        '‘aa’ requires its first and second arguments ' +
                        'to be of the same type; 0 and false are not'));

  assert.throws(function() { aa(R.__, false)(0); },
                errorEq(TypeError,
                        '‘aa’ requires its first and second arguments ' +
                        'to be of the same type; 0 and false are not'));

  assert.throws(function() { abba(0, [], {}); },
                errorEq(TypeError,
                        '‘abba’ requires its second and third arguments ' +
                        'to be of the same type; [] and {} are not'));

  assert.throws(function() { abba(0, [], [], ''); },
                errorEq(TypeError,
                        '‘abba’ requires its first and fourth arguments ' +
                        'to be of the same type; 0 and "" are not'));
});
Noam Lewis
@sinelaw
Oct 27 2015 18:59
joneshf-work1: not sure, last I checked the maintainer wanted more thorough tests
davidchambers: looks perfectly clear
you could add a type signature in a comment near the top
on aa, ab, abba
David Chambers
@davidchambers
Oct 27 2015 19:01
Good idea. I'll add type signatures. I was wondering whether the description itself could be more descriptive. If it makes sense to you, that's good enough for me. :)
Noam Lewis
@sinelaw
Oct 27 2015 19:01
type signatures are unambiguous
David Chambers
@davidchambers
Oct 27 2015 19:02
//  aa :: a -> a -> (a, a)
var aa = def('aa', [a, a], list);
//  ab :: a -> b -> (a, b)
var ab = def('ab', [a, b], list);
//  abba :: a -> b -> b -> a -> (a, b, b, a)
var abba = def('abba', [a, b, b, a], list);
Noam Lewis
@sinelaw
Oct 27 2015 19:03
looks good
Noam Lewis
@sinelaw
Oct 27 2015 20:20
lovely: ecmascript the array [,,] syntax
Raine Virta
@raine
Oct 27 2015 20:50
anyone familiar with esprima ast traversal? what's a nice way to mutate ast?
s/mutate/manipulate/
Scott Christopher
@scott-christopher
Oct 27 2015 20:52
perhaps lenses?
Raine Virta
@raine
Oct 27 2015 21:03
perhaps... i understand lenses are fixed though
this api is not really doing it for me
types.visit(ast, {
  visitVariableDeclaration: (path) => {
    path.replace(b.returnStatement(
      b.callExpression(b.identifier('foo'), [ ])
    ))

    return false;
  }
})
Scott Christopher
@scott-christopher
Oct 27 2015 21:10
just reading up on Esprima
Scott Christopher
@scott-christopher
Oct 27 2015 21:21
If can convert path in your example there to a composition of lensIndex and lensProp functions, then you should be able to achieve something like:
R.set(lensPath, returnStatement(callExpression(identifier('foo'), [])), ast);
Raine Virta
@raine
Oct 27 2015 21:23
how would a lens be used to "find first occurrence of something in an object tree"?
Scott Christopher
@scott-christopher
Oct 27 2015 21:24
Do you have a simple example of some JS to be parsed?
Raine Virta
@raine
Oct 27 2015 21:26
as a trivial example var add = (a, b) => a + b
which becomes http://ix.io/lEq
I'd probably want to map the first { type: 'VariableDeclaration' }
Scott Christopher
@scott-christopher
Oct 27 2015 21:36
I've got a suspicion that a traversal would be needed rather than a lens, which lets you focus on 0 or more targets of something.
Raine Virta
@raine
Oct 27 2015 21:37
so that's what it's called
Denis Stoyanov
@xgrommx
Oct 27 2015 22:09
Hi guys! I have created some example with Ramda, Rx now. This is single select, multi select with ctrl and range select with shift. http://jsfiddle.net/xgrommx/a9m50xev
Denis Stoyanov
@xgrommx
Oct 27 2015 22:38
A need some help
I don't understand why this code works const fromKeyDown = code => fromKey(code, 'keydown'); but this doesn't const fromKeyDown = always(fromKey(__, 'keydown'));
David Chambers
@davidchambers
Oct 27 2015 22:49
You probably want something like this, @xgrommx:
const fromKey = R.curry((type, code) => …);

const fromKeyDown = fromKey('keydown');
I don't think you want always at all.
Denis Stoyanov
@xgrommx
Oct 27 2015 22:52
yep! thank. I should make my example more Ramdality))
but this one const fromKeyPress = code => fromKeyDown(code).map(true).merge(fromKeyUp(code).map(false)).shareValue(false); can I use Ramda?
David Chambers
@davidchambers
Oct 27 2015 23:23
Could you provide example input and output?