These are chat archives for ramda/ramda

8th
Jul 2016
James Forbes
@JAForbes
Jul 08 2016 02:23

@CrossEye

I worry very little about points-free. I think very much more about creating useful functions that capture the meaning is some of these operations.

Sorry I don't think my point was made clearly enough. I don't care about point free either. The point I was attempting to make was that point free is the only context where gt is useful.

gt is only useful as a unary because If you have both inputs, then you can just use the native JS operator directly.

Though now i've said that, I'm Imagining some pretty crazy code that may actually use it as a binary...

Scott Sauyet
@CrossEye
Jul 08 2016 02:42

I mentioned above that I do use it that way. I often have a generic function to which I pass arbitrary predicates, including mathematical ones like this.

But there is certainly an argument to be made for signatures like gt :: Ord a => a -> (a -> Bool), to replace the current gt :: Ord a => a -> a -> Bool. That would feel odd in Ramda, where very few functions are written this way, and those ones don't really present us with options.

But this whole mess makes that seem more reasonable. I still lean to the glosses, though, such as isGt, which documentation links between them.
James Forbes
@JAForbes
Jul 08 2016 02:45
Hmmm sorry @CrossEye I missed that point I think
Could you post a sample of the generic function that receives arbitrary predicates? I'd really like to see an example
Scott Sauyet
@CrossEye
Jul 08 2016 03:08

I discussed working with polygons in a comment some time back. That gives a bit of a flavor of working with random (x, y) predicates. Often I use things like aboveDiagonal = R.gt and belowDiagonal = R.lt.

But I also do work with arbitrary calculations, involving storing a structure representing a calculation as a series of binary steps, each one with a string such as "subtract" or "multiply" pointing to an actual function that will be invoked on the operands. That has a similar feel, although I have only just started to think about including such predicates in order to create multi-part functions (like f(x) = x * x, if x < 0, 2x -1, if x >= 0. For the one-dimensional case, unary predicates would be fine. But my system also works in the plane, and then I might need more complex predicates. I don't know if I would ever really need these simple predicates such as gt in this system, but it's a place I use that sort of function.

Going to bed. Can pick this up again tomorrow if there's more interest. I really would like to end up with a useful solution.
James Forbes
@JAForbes
Jul 08 2016 03:18
That's really fascinating!
Thank you @CrossEye
Ebrahem Al-Hajeri
@ehajri
Jul 08 2016 05:51
Is there an easy/convenient way to transform an object, with some properties being objects, into a 1 dimension list?
Ebrahem Al-Hajeri
@ehajri
Jul 08 2016 06:16
I am falling in love with Ramda
var filter = function(claims) {
    return R.flatten(
        R.keys(sections).map(
            function(t) {
                var s = pH.sections[t];
                return s.sub ? [].concat(s, s.sub) : s;
            }
        )
    ).filter(
        function(r) {
            return R.contains('Administrator', claims) ||
                   (R.has('claims')(r) && (
                        R.equals('any', r.claims) ||
                        R.intersection(claims, r.claims.split(',')).length > 0
                   ));
        }
    );
}
Jigar Gosar
@jigargosar
Jul 08 2016 12:28
@ehajri +1
it has changed my life, 15 years of programming in java/js and now I discover FP, all thanks to ramda.
I keep feeling that there must be a better way of doing what I am doing, feel like a total noob, reminds me of my younger days, when I used to 7-8 rewrites of entire project ;)

Quick question
Quick

_.reduce(function (acc, stateKey) {
        return _.assoc(stateKey, getter, acc)
    }, {}, stateKeys)

Any simpler way to do this, I writing this pattern, thought of extracting the code. But I have a feeling its already there somewhere in ramda.

Jigar Gosar
@jigargosar
Jul 08 2016 12:34
maybe using some transducer/into functions? I haven't been able to find good use for them in my projects, am surely missing something.
Rafe
@rjmk
Jul 08 2016 12:45
Probably not simpler, but arguably more abstract is mergeAll(map(flip(objOf)(getter), stateKeys))
Jigar Gosar
@jigargosar
Jul 08 2016 12:51
quick question about ramda-fantasy: is there a single js file available like ramda? I couldn't find it on any cdn, also what is recomended ramda-fantasy or sanctuaryjs? for using Maybe/Either/IO
Martin Broder
@mrtnbroder
Jul 08 2016 15:25
Hey everyone
general question: why to people like to use compose over pipe?
like, right to left composition
Raine Virta
@raine
Jul 08 2016 15:26
might be a habit of mathematically inclined people and also of those coming from haskell
James Forbes
@JAForbes
Jul 08 2016 15:26
I personally prefer pipe. But I think some people prefer compose because right to left mimicks real composition:
h(g(f(a))) -> compose(h,g,f)(a)
Martin Broder
@mrtnbroder
Jul 08 2016 15:26
is there no such thing in haskell? pipe I mean?
James Forbes
@JAForbes
Jul 08 2016 15:27
So if you think of composition as h(g(f(a))) you would probably see pipe as being "backwards"
Martin Broder
@mrtnbroder
Jul 08 2016 15:28
makes sense
Brad Compton (he/him)
@Bradcomp
Jul 08 2016 15:29
I like compose because visually, you pass the data into the right side of the function and the result comes out the left side
James Forbes
@JAForbes
Jul 08 2016 15:31
I like it in different situations. If I'm thinking "I'm transforming some input" I like pipe. If I'm creating a virtual dom view, I like compose
compose(
  div
     ul
       map(li)
)
Martin Broder
@mrtnbroder
Jul 08 2016 15:38
@JAForbes THAT is easy to read, I agree :D
James Forbes
@JAForbes
Jul 08 2016 15:39
:)
Brad Compton (he/him)
@Bradcomp
Jul 08 2016 15:40

is there no such thing in haskell? pipe I mean?

I don't know about Haskell, but Purescript has both >>> and <<< as their composition operators

Martin Broder
@mrtnbroder
Jul 08 2016 15:40
ugh >>> why not simple `
argh
simply |> = pipe
and maybe |< for compose
Emilio Srougo
@Emilios1995
Jul 08 2016 15:46
In Elixir pipe is the default way to compose. |>
Brad Compton (he/him)
@Bradcomp
Jul 08 2016 15:46
Looks like they're maybe based on Control.Arrow in Haskell
Martin Broder
@mrtnbroder
Jul 08 2016 15:47
ah
Denis Stoyanov
@xgrommx
Jul 08 2016 15:49
@Bradcomp alternative for Control.Arrow will be Data.Bifunctor + Control.Applicative
Brad Compton (he/him)
@Bradcomp
Jul 08 2016 16:07

@jigargosar

what is recomended ramda-fantasy or sanctuaryjs?

Sanctuary has a lot of nice features like runtime type checking, and 'safe' versions of Ramda functions that return Maybe's instead of undefined. It also doesn't have an IO type that I'm aware of. It's a good choice, but very opinionated, so I guess it depends on what you want to do. If you just want the containers without the type checking and helper functions, I would probably consider ramda-fantasy or folktale (I'm sure there are others too).

Brad Compton (he/him)
@Bradcomp
Jul 08 2016 17:06

Does this seem like a useful operator to anybody? http://goo.gl/Bwrbi8

Is there a more useful form of this, or a builtin that does something similar?

Emilio Srougo
@Emilios1995
Jul 08 2016 17:10
@Bradcomp Isn't it like useWith?
Brad Compton (he/him)
@Bradcomp
Jul 08 2016 17:12
It's similar. I guess useWith is the more general form: const on = (f, g) => useWith(f, [g, g])
Drew
@dtipson
Jul 08 2016 17:14
Spent the night trying to think though what signature difference is implied between gt :: Ord a => a -> (a -> Bool) and gt :: Ord a => a -> a -> Bool
Emilio Srougo
@Emilios1995
Jul 08 2016 17:14
Oh, right. Then I guess it's more like converge
Denis Stoyanov
@xgrommx
Jul 08 2016 17:15
@Bradcomp in haskell exists useWith and converge?
Brad Compton (he/him)
@Bradcomp
Jul 08 2016 17:16
@xgrommx My forays into Haskell are limited, but I haven't run across them. I learned about on in the Purescript book I think.
Denis Stoyanov
@xgrommx
Jul 08 2016 17:16
@Emilios1995 converge has another behaviour unlike of useWith
@Bradcomp this operator in Data.Function in haskell
Drew
@dtipson
Jul 08 2016 17:17
I prefer compose, but when you're trying to explain a composition by splitting it out with newlines, pipe is more natural (since in that case, it reads top to bottom, instead of bottom up)
Emilio Srougo
@Emilios1995
Jul 08 2016 17:19
@xgrommx What I'm saying is that @Bradcomp 's on looks very similar to converge. Am I right?
Brad Compton (he/him)
@Bradcomp
Jul 08 2016 17:20
@Emilios1995 I think you were more right the first time. It's very similar to useWith
Denis Stoyanov
@xgrommx
Jul 08 2016 17:23
@Emilios1995 no, on is one of form of useWith
@Emilios1995 converge apply all arguments for each function, but useWith apply per argument
Emilio Srougo
@Emilios1995
Jul 08 2016 17:40
Oh, right. It's more similar to useWith. In fact, the examples of useWith in the docs are a better fit for on, since it applies the same function to both args
Emilio Srougo
@Emilios1995
Jul 08 2016 17:46
No, forget it. I's just the identity function that it's used on both args, and the docs explain why
Denis Stoyanov
@xgrommx
Jul 08 2016 18:23
I think converge might be to removed http://goo.gl/6K92iG
Denis Stoyanov
@xgrommx
Jul 08 2016 18:55
Or use sequenceA http://goo.gl/Bvi2tU
David Chambers
@davidchambers
Jul 08 2016 19:01
@dtipson, a -> (a -> Bool) implies that the function takes exactly one argument, whereas a -> a -> Bool implies a binary function curried Ramda-style (which can receive its arguments one at a time or both at once).
Denis Stoyanov
@xgrommx
Jul 08 2016 19:02
@ram-bot
compose(sum, sequence(always)([add, multiply]))(10, 20)
ram-bot
@ram-bot
Jul 08 2016 19:02
230
Denis Stoyanov
@xgrommx
Jul 08 2016 19:02
@ram-bot
converge(add, [add, multiply])(10, 20)
ram-bot
@ram-bot
Jul 08 2016 19:02
230
David Chambers
@davidchambers
Jul 08 2016 19:03
@JAForbes, the inverse of R.gt is not R.lt but R.lte. :wink2:
Denis Stoyanov
@xgrommx
Jul 08 2016 19:03
@ram-bot
lift(add)(add, multiply)(10, 20)
ram-bot
@ram-bot
Jul 08 2016 19:03
230
Denis Stoyanov
@xgrommx
Jul 08 2016 19:04
converge is unnecessary operator :smile:
David Chambers
@davidchambers
Jul 08 2016 19:04
@ram-bot
S.lift2(S.add, S.add, S.mult)(10, 20)
ram-bot
@ram-bot
Jul 08 2016 19:04
230
Denis Stoyanov
@xgrommx
Jul 08 2016 19:04
But I don't think that with sequence, lift will be replaced useWith
Gabe Johnson
@gabejohnson
Jul 08 2016 19:11
@davidchambers @JAForbes and i were talking about the converse, not the inverse
Denis Stoyanov
@xgrommx
Jul 08 2016 19:18
@ram-bot
useWith(add)([add(10), multiply(20)])(1, 2)
ram-bot
@ram-bot
Jul 08 2016 19:18
51
Denis Stoyanov
@xgrommx
Jul 08 2016 19:19
@ram-bot
compose(apply(add), zipWith(call, [add(10), multiply(20)]), unapply(identity))(1, 2)
ram-bot
@ram-bot
Jul 08 2016 19:19
51
Denis Stoyanov
@xgrommx
Jul 08 2016 19:19
ugly version :smile:
David Chambers
@davidchambers
Jul 08 2016 20:55
Could you explain the difference between converse and inverse, @gabejohnson?

I was referring specifically to this comment by @JAForbes:

all the same, one could still substitute gt for lt as a migration, even when they've flipped or used a placeholder.

Whether this is the converse or the inverse I don't know, but the correct substitution is :%s/\<R\.gt\>/R.lte/g I believe.