These are chat archives for ramda/ramda

1st
Apr 2016
Drew
@dtipson
Apr 01 2016 00:38
Was trying to work out a pickByIndex (the one in the cookbook doesn't really work for my purposes) and ran into something I can't quite figure out.
This works perfectly well:
compose(ap, map(nth))([0,2,2,3,4,1])([['a','b','c','d','e','f','g']])
But I'd prefer the signature not require the extra call to of for the sample source. So I tried this:
const pickByIndex = useWith(
  compose(ap, map(nth)),
  [identity, of]
);
But that returns a function instead of a result. I think something in the realm of arity is getting mucked up, but I can't for the life of me figure out what
Usage would just be this:
const specificPick = pickByIndex([0,2,2,3,4,1]);
...
specificPick(['a','b','c','d','e','f','g'])
Drew
@dtipson
Apr 01 2016 00:43
all part of a coding exercise for a check-digit verification where I'm slowly trying to eliminate all reference to intermediate arguments and show off what Ramda can do with a complex set of requirements: http://goo.gl/HThlrw
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 04:20
is there a mistake in the type sig for addIndex on the doc site?
((a … → b) … → [a] → ) → (a …, Int, [a] → b) … → [a] → )
the parens seem screwy
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 04:26
Scott Sauyet
@CrossEye
Apr 01 2016 11:10
Yes, the third opening paren should be two opening parens.
it's one of the most convoluted signatures we have.
Lewis
@6ewis
Apr 01 2016 12:29
anyone use golang/clojure?
@CrossEye @Bradcomp Can you give me exercises so i get familiar with ramda.js?
Hardy Jones
@joneshf
Apr 01 2016 12:56
What is the proper type there?
Lewis
@6ewis
Apr 01 2016 12:57
@joneshf you too :package:
Hardy Jones
@joneshf
Apr 01 2016 13:01

Something like this seems reasonable as an actual signature that would type check:

addIndex :: ((a -> b) -> [a] -> c) -> (Number -> a -> b) -> [a] -> c

But that's not what it's actually doing.

@6ewis I think this is pretty good if you do the exercises in ramda: http://reactivex.io/learnrx/
Hardy Jones
@joneshf
Apr 01 2016 13:07
@6ewis one way you can do that is to copy paste https://cdnjs.cloudflare.com/ajax/libs/ramda/0.20.1/ramda.min.js into the console
It'll put R on the window, so you can access it within the exercises.
For instance, the first exercise says to use forEach on the array prototype. Instead you could use R.forEach
Lewis
@6ewis
Apr 01 2016 13:34
@joneshf it seems to easy but not a bad idea
Scott Sauyet
@CrossEye
Apr 01 2016 13:41
@joneshf: the trouble is that addIndex works not only for binary functions, but also ternary or general n-ary ones. Moreover it works with polyadic callback functions too. Thus it works both with map:: (a -> b) -> [a] -> [b] but also with reduce:: (b -> a -> b) -> b -> [a] -> b.
Hardy Jones
@joneshf
Apr 01 2016 13:50

@CrossEye right, so it wouldn't work with reduce as is, but if you flip some args it would. If we had:

reduce :: (a -> b -> b) -> [a] -> b -> b

It would type check, since we could add parentheses to get something like:

reduce :: (a -> (b -> b)) -> [a] -> (b -> b)

Then we have:

  • a in addIndex unifies with the a in reduce
  • b in addIndex unifies with the b -> b in reduce
  • c in addIndex unifies with the b -> b in reduce
But it seems wrong to have to do that as well.
well, not really wrong
cumbersome
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 15:09
@CrossEye, I'm somewhat familiar w/ ramda's type sigs as I've spent a little time w/ purescript and haskell (though not a lot, still learning); however, I'm not sure how to "read aloud" the ... in the sigs
i appreciate your pointing out where the paren is missing in the sig for addIndex, but the various "..." are still confusing me a bit, as far as how to read them, though I do understand what addIndex does
Lewis
@6ewis
Apr 01 2016 15:20
::addIndex
Brad Compton (he/him)
@Bradcomp
Apr 01 2016 15:21
@6ewis The Mostly Adequate Guide has exercises (starting in chapter 4), and they actually use Ramda as the library.
Lewis
@6ewis
Apr 01 2016 15:21
@Bradcomp thanks funny enough i read it up to chapter 3
Brad Compton (he/him)
@Bradcomp
Apr 01 2016 15:46
@6ewis Have you seen the Advent of Code problems? It's not Christmas but they're still fun, and code puzzles are a great opportunity for learning a new paradigm / library / language
LeonineKing1199
@LeonineKing1199
Apr 01 2016 16:15

Almight Ramda gurus, masters of the functional paradigm, why does compose with transduction seem to reverse the order of compose? Example,

let transducer = R.compose(R.filter(R.gte(R.__, 15)), R.map(R.add(13)))
R.transduce(transducer, R.flip(R.append), [], R.range(0, 20))
// output: [28, 29, 30, 31, 32]

It looks like the application of functions is from left to right even though compose is supposed to go from right to the left, right?

Lewis
@6ewis
Apr 01 2016 16:19
@Bradcomp are they problems that require a functional approach to be solved?
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 16:19
@LeonineKing1199 compose goes from right to left, but a transducer stack processes left to right?
sorry, didn't meant to put '?' on the end, I was making a statement
@LeonineKing1199 to understand that, look at how compose works together with the function that's returned by a transducer, e.g. R.map (when called w/ one arg)
Drew
@dtipson
Apr 01 2016 16:27
you're basically composing configuration rather than values: compose is still working right to left: but what it's passing right to left are partial functions that are used at the end of each operation they're getting passed into
I wrote up a longer explanation at the end of this transducer article: https://medium.com/@dtipson/everything-reduced-transducers-in-javascript-8ea3459bc7f9
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 16:29
I'm looking at ramda's source code now, and it's a little bit hard to follow what's going on; I suggest looking at the definition of clojure's comp function and the single-arg impl for clojure's map function
it's easier to see therein how the right-to-left composition result gets turned inside out
to result in the transformer stack being applied left-to-right
LeonineKing1199
@LeonineKing1199
Apr 01 2016 16:32

Lol I actually realized exactly what Ramda was doing. I remembered this article: http://phuu.net/2014/08/31/csp-and-transducers.html

and then I realized that Ramda is composing from right to left, it's just not how I would think of it. In my example, the map is the overarching function while the filterererererer is the nested. So it's like a reverse sort of hierarchy

Drew
@dtipson
Apr 01 2016 16:33
check out these stripped down gists: composing functions that consume functions for a tail operation and then return configured functions: https://gist.github.com/dtipson/a06f1c549721f4e79dfc#file-composition-higher-order-js vs composing functions that just consume and return values https://gist.github.com/dtipson/8577067066732795575d#file-compose-just-values-js
LeonineKing1199
@LeonineKing1199
Apr 01 2016 16:34

Using this as an example of what Ramda might conceptually implement,

function mapping(transform) {
    return function (reduce) {
        return function (result, input) {
            return reduce(result, transform(input));
        };
    };
}

function filtering(predicate) {
    return function (reduce) {
        return function (result, input) {
            return (
                predicate(input) ?
                    reduce(result, input) :
                    result
            );
        };
    };
}

Looking at this, I now see how the composition works.

Michael Bradley
@michaelsbradleyjr
Apr 01 2016 16:37
correct, the left-most argument of compose ends up corresponding to the the outer-most function in the transformer stack, so that its effects happen first
LeonineKing1199
@LeonineKing1199
Apr 01 2016 16:48
@michaelsbradleyjr Yes! Exactly! I realized that literally like 2 minutes after I posted here lol :P
God, transducers are cool. I, like, need to know how all of this works on a lower-level...
Drew
@dtipson
Apr 01 2016 16:53
there are some standalone libraries which might lay it out more directly: https://github.com/jlongster/transducers.js
that article of mine that I linked also walks through building them directly (in a slightly less powerful form, since there's no transducer protocol, so I have to resort to special Symbol keys and a custom reduce to implement things like take)
LeonineKing1199
@LeonineKing1199
Apr 01 2016 16:57
Yeah, I bookmarked the link. I'll check it out when I have time :)
Brad Compton (he/him)
@Bradcomp
Apr 01 2016 17:04

@Bradcomp are they problems that require a functional approach to be solved?

@6ewis I wouldn't say they require a functional approach, but many of them have good functional solutions.
If you want some specific problems for learning FP, there's 99 Haskell Problems

Lewis
@6ewis
Apr 01 2016 17:36
@Bradcomp thank you exactly the kind of stuff I was looking for
Brad Compton (he/him)
@Bradcomp
Apr 01 2016 17:37
:+1:
Scott Sauyet
@CrossEye
Apr 01 2016 18:08
@michaelsbradleyjr: still incomplete, but a start at explaining our type sigs: https://github.com/ramda/ramda/wiki/Type-Signatures. The ellipsis represent repetition. "There are some number more similar elements here. "
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 18:21
@CrossEye thanks, so can you help me "read" the sig for the first arg of addIndex?
((a … → b) … → [a] → *)
so, altogether, that argument could be something like R.map
i read the first ... as saying that the function we'd expect as the first arg to, say, R.map, could be variadic in its arguments; e.g. a or a, a, or a,a,a,...
but the second ..., what does it represent? can you give an example?
clojure's map, for example, allows multiple collection as the 2nd...nth args
but I don't see how to interp. the second ... in that manner
but maybe that arg's type sig should be ((a … → b) → [a] ... → *)
Tobias Pflug
@gilligan
Apr 01 2016 18:28
good evening
oh boy i haven't been here for way way too long
Scott Sauyet
@CrossEye
Apr 01 2016 18:35
hi, @gilligan!
Tobias Pflug
@gilligan
Apr 01 2016 18:36
real life took over.. time to have add more ramda to my life again ;)
Scott Sauyet
@CrossEye
Apr 01 2016 18:36
@michaelsbradleyjr: T
Tobias Pflug
@gilligan
Apr 01 2016 18:36
seems like there was another gitter client update. Seems like it improved a bit
Scott Sauyet
@CrossEye
Apr 01 2016 18:39
Hee's a simplification that doesn'hat could take for instance, map:: ((a -> b) -> [a] -> [b]) and convert it to `addIndex(map):: (a-> Number -> [a] -
t
god, I hate the mobile client that won't let me edit!
so yes @gilligan, some improvements, but not nearly enough.
Let me try again.
I'm going to talk about a simplified addIndex that adds only the index and not also the collection to the callback.
Tobias Pflug
@gilligan
Apr 01 2016 18:41
@CrossEye compared to slack it is still pretty bad- yes
Scott Sauyet
@CrossEye
Apr 01 2016 18:41
It converts map:: ((a -> b) -> [a] -> [b] to addIndex(map):: (a -> Number -> b) -> [a] -> [b].
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 18:45
@CrossEye i got that, makes sense; the 2nd ellipsis in the first arg doesn't make sense to me
Scott Sauyet
@CrossEye
Apr 01 2016 18:45
But this same function converts reduce:: ((b-> a -> b) -> b -> [a] -> [b] to addIndex(reduce):: ((b-> a -> Number -> b) -> b -> [a] -> [b].
Note that the number of arguments to the callback varies.
The first one has one argument, the second one has two. This is agnostic to that arity. It adds Number as an additional parameter.
(In the real function, it also adds the entire list as a parameter to the callback.)
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 18:49
yes, that makes sense too, I still don't get the second ellipsis here: (a … → b) …
Scott Sauyet
@CrossEye
Apr 01 2016 18:49
Sorry, the second ellipsis has to do not with the callback but with the function as a whole. map is binary. reduce is ternary. We can imagine even larger arguments lists.
(didn
(didn't see your response until I'd finished typing all the reduce stuff. I can be blind.)
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 18:51
np, and I can move on w/ a general sense of how to use it; I don't readily parse those two ellipsis into the binary,ternary,4+ meaning
I realize that ramda faces some challenges here, given the dynamism w.r.t. types and arity
Scott Sauyet
@CrossEye
Apr 01 2016 18:52
So in map the second ... represents an empty list of arguments. In reduce it represents b
the argument(s) between the callback and the list of [a]'s.
and in addIndex(:: (a -> b) -> c -> d -> e -> [a]) it would represent c, d, e.
sorry, that wasn't complete, but the notation is invented anyway.
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 18:56
so why isn't it ((a … → b) → … → [a] → *) vs. ((a … → b) … → [a] → *)
or the is implied if a type variable is followed by ...?
Scott Sauyet
@CrossEye
Apr 01 2016 18:57
Just a real inconsistency in how various people create these. I think it should have the arrow.
But even throughout this conversation, I didn'
didn'
t notice it missing until now.
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 18:58
so, to be consistent, we could have: ((a → … → b) → … → [a] → *)
Scott Sauyet
@CrossEye
Apr 01 2016 18:58
Yes, that would be better. And a PR for that would be welcome.
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 18:59
ok
Scott Sauyet
@CrossEye
Apr 01 2016 18:59
It's a shame that this is one of the earliest functions alphabetically. :smile:
thanks for persevering. I was clearly missing the point.
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 18:59
now, I could see in some cases, where one might not expect a function to be curried, to use tuple notation
which I've seen in purescript
something like: ( ( ( (a, …) → b ), …) → [a] → *)
the parens start to get a little heavy, though; but one could, say, use {} to denote tuples
Scott Sauyet
@CrossEye
Apr 01 2016 19:02
yes, we're also inconsistent about this. We probably could use tuples in callbacks where we never take advantage of the currying.
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 19:03
({({a, …} → b ), …} → [a] → *)
just thinking aloud on that one, not sure it's really better
Scott Sauyet
@CrossEye
Apr 01 2016 19:04
See #1554 for discussions about this... not yet resolved. But your contributions would be most welcome.
Michael Bradley
@michaelsbradleyjr
Apr 01 2016 19:04
anyway, thanks for entertaining my inquiries! :-)
Scott Sauyet
@CrossEye
Apr 01 2016 19:05
my pleasure.
Asaf
@asaf-romano
Apr 01 2016 19:48
Does this seem useful to anyone http://goo.gl/QJ03To ?
Scott Sauyet
@CrossEye
Apr 01 2016 19:52
I'm absolutely certain that on a few occasions I've needed exactly that, but I don'
t recall any details now.
Tobias Pflug
@gilligan
Apr 01 2016 19:55
huh.. you have some really weird, unusual indentation going in there @asaf-romano hehe
anyway - never found myself doing/needing that actually
LeonineKing1199
@LeonineKing1199
Apr 01 2016 20:00
I like it. It's actually read-able.
Asaf
@asaf-romano
Apr 01 2016 20:31
it's an operator in mongo's aggregation system, and at least there it's remarkably useful
I'm not sure whether it should act on a single object (as the repl script does) or on a collection ("auto"-chain)