These are chat archives for ramda/ramda

10th
Sep 2015
Scott Sauyet
@CrossEye
Sep 10 2015 00:37
@davidchase: This is fantastic! I've been saying for ramda/ramda#1000 that we needed to give the REPL some love. This looks like a lot of love!
Jethro Larson
@jethrolarson
Sep 10 2015 01:12
I you have algebraic types like Maybe or Future, what's a good way to define/query what their type is?
var fTypeOf = v => v.prototype.constructor.name ?
some kind of @@property?
David Chambers
@davidchambers
Sep 10 2015 01:12
In theory you should know what you're dealing with.
Libraries may make this sort of introspection possible, though.
Jethro Larson
@jethrolarson
Sep 10 2015 01:14
well, say you want a generic map function, but don't want to define map on the prototype of your objects
David Chambers
@davidchambers
Sep 10 2015 01:14
For example:
> require('sanctuary').Just(42).type.name
'Maybe'

say you want a generic map function, but don't want to define map on the prototype of your objects

That would depend on implementation details of Maybe and Future, unfortunately.

Scott Sauyet
@CrossEye
Sep 10 2015 01:20
@jethrolarson: I'm actually not spending much time on Ramda stuff right now -- partly because I'm a little burned out on all my side project -- but in good part because I'm working on an idea for allowing you to define fantasy-land-style types without OO-style methods. It's still in early stages, but I think it will work. Whether it would be actually useful or just a curiosity is still not clear, though.
Jethro Larson
@jethrolarson
Sep 10 2015 01:20
Well I was thinking of something like
var Maybe = require(./'maybe');
var List = require('./list');
var {map, chain} = require('./myFantasy')({Maybe, List});
I am thinking the same thing. Keeping dependencies from getting intertwined is on my mind.
Then
map(add(1))([1]) == [2]
map(add(1))(Just(1)) == Just(2)
David Chambers
@davidchambers
Sep 10 2015 01:25
I see the appeal. :)
Jethro Larson
@jethrolarson
Sep 10 2015 01:26
Which I know ramda can do if you define all the Maybe functions on the prototype but maybe there's another way?
I've also been trying to figure out what should replace SOLID for this stuff. Injecting the implementations into the interface is my naive attempt at Dependency Inversion.
David Chambers
@davidchambers
Sep 10 2015 01:30
What is SOLID?
Scott Sauyet
@CrossEye
Sep 10 2015 01:31
Mine will have an API something like
// in Maybe.js 
LibName.registerMonoid(Maybe, {
    concat: someFunc,
    empty: anotherFunc
});

// in code that uses it:
var {concat, empty, map, of, ap, ...} = require('./LibName')
concat(Just(Multiply(6), Just(Multiply(7)); //=> Just(Multiply(42))
Scott Christopher
@scott-christopher
Sep 10 2015 01:32
That sounds similar to how I wanted to try tackle dispatching in Ramda previously
Scott Sauyet
@CrossEye
Sep 10 2015 01:33
Yes, this will have nothing to do with Ramda.
But I wasn't aware that you were thinking that way. Did you propose it?
Scott Christopher
@scott-christopher
Sep 10 2015 01:34
It came up in discussion some time ago, but it was at a time where there was push back on dispatching in general.
Jethro Larson
@jethrolarson
Sep 10 2015 01:35
Here's me effort on the interface
module.exports = xface => {
  const ftype = a => a['@@type']

  //:: S a -> S b -> Boolean
  const equals = a => b => xface[ftype(a)].equals(a, b)
  return {equals}
}
Arrr
Scott Sauyet
@CrossEye
Sep 10 2015 01:38

For Ramda, I've been mostly happy with the quiet dispatch; you got it, we'll call it. However, a style like this would of course make it much more possible to dispatch to many other systems, things like mori, which we can't handle at all now, as they have an API much more FP than OO.

One concern would be that of breaking referential integrity with a registration model. We might have to return a new instance of Ramda in order to avoid that.

Scott Christopher
@scott-christopher
Sep 10 2015 01:42
That was the approach that I took with my proof of concept. You basically register everything, producing a new R at the end of it.
Scott Sauyet
@CrossEye
Sep 10 2015 01:43
We actually have an issue or pr open for something like this, for integration with Immutable. I don't know if any further progress has been made since I suggested something like that.
David Chase
@davidchase
Sep 10 2015 01:43
@CrossEye thanks for the kind words about the repl, maybe i can help out on the #1000
Scott Christopher
@scott-christopher
Sep 10 2015 01:45
https://github.com/puffnfresh/bilby.js/blob/master/src/environment.js is more or less the same approach I was playing with
Scott Sauyet
@CrossEye
Sep 10 2015 01:48
Yes, someone brought that up when we discussed this some time ago. I've only barely played with Bilby. I really should give it a serious try.
@davidchase: It would be great if you could. What you've done there is wonderful. (One little thing: I wasn't able to copy text from the REPL. Just tried it for a Gitter discussion.)
Scott Christopher
@scott-christopher
Sep 10 2015 01:51
If someone feels really inspired, I'd love to see a repl incorporated into the docs somehow.
It would be great to have a "Load example in REPL" feature
Scott Sauyet
@CrossEye
Sep 10 2015 01:51
One idea I mentioned in #1000 was to make every code example in the docs have an icon that launched it in the REPL.
Scott Christopher
@scott-christopher
Sep 10 2015 01:54
That should be pretty straightforward to add with the current URL hash support (providing the examples aren't too long)
It would be nice if we didn't have to leave the docs page to play with the REPL though
and getting the docs mobile friendly would be great too.
Scott Christopher
@scott-christopher
Sep 10 2015 01:56
I'm unfortunately severely lacking the necessary CSS skill set :P
Scott Sauyet
@CrossEye
Sep 10 2015 01:56
Actually, I believe they will be better on the next publish.
ramda/ramda.github.io#24
ramda/ramda.github.io#25
Scott Christopher
@scott-christopher
Sep 10 2015 01:58
^ this looks much nicer
Look forward to it :)
David Chase
@davidchase
Sep 10 2015 01:59
were you not able to copy from the output or input side @CrossEye ?
Jethro Larson
@jethrolarson
Sep 10 2015 02:05
With my scheme the implementations of the interface are parameters to the library so if you want to add support for streams or vector tries you don't have to change the library. You just provide an implementation that conforms to the interface
It also means that I don't have to modify object prototype to add hash methods, nor modify array prototype
Just need to modify the ftype function to check for what constitutes an array
Scott Sauyet
@CrossEye
Sep 10 2015 02:07
@davidchase : Input. I just tried output and could do it.
Jethro Larson
@jethrolarson
Sep 10 2015 02:07
since unfortunately that's not straightforward in js
David Chase
@davidchase
Sep 10 2015 02:08
hmm odd i was able to copy from both input and output
Scott Sauyet
@CrossEye
Sep 10 2015 02:11
Hmm, FF 38, Kubuntu 14.04. Not a big deal, certainly not at the moment.
David Chase
@davidchase
Sep 10 2015 02:14
still interesting to figure why it doesnt work.. tried on my FF but i have mac osx, can you copy from input on the ramda repl?
Scott Sauyet
@CrossEye
Sep 10 2015 02:15
yes I can.
Maybe it's an Ubuntu thing. I just had the same issue on Chromium.
David Chase
@davidchase
Sep 10 2015 02:23
might just be that, because chromium worked for me as well, odd since i mostly only updated the css :disappointed:
Scott Sauyet
@CrossEye
Sep 10 2015 02:24
odd, but I'm not going to worry about that now.
David Chase
@davidchase
Sep 10 2015 02:29
understood
Jethro Larson
@jethrolarson
Sep 10 2015 03:30
Updated gist with configurable type checking so no array implementation details need be baked in. Implementations can just provide a typeEvaluator
Chet Harrison
@ChetHarrison
Sep 10 2015 04:23
ok. I'm sure this is not the first time this has been asked but ... when I look through every post on the various Monads out there it seems like every one has a different API eg is it "bind" or "flatMap" or "chain" or is it "unit" or "pure" or "of". I know this is not Ramda's problem but you are obviously fans of this excellent paradigm.
So ...
This would suggest that, within JS, there needs to be some standards. I have found some in the fantasyland, which sounds a bit strange just trying to take that seriously but I like a good joke. And ...
What JS Monadic libs have you all taken inspiration from?
Scott Christopher
@scott-christopher
Sep 10 2015 04:27
I think a lot of the JS community has settled on chain, as per the fantasy land spec.
bind is already taken via function.prototype.bind
Chet Harrison
@ChetHarrison
Sep 10 2015 04:29
I do like chain vs bind
I like of vs anything else
Scott Christopher
@scott-christopher
Sep 10 2015 04:30
I haven't seen many (if any) JS implementations use flatMap.
Chet Harrison
@ChetHarrison
Sep 10 2015 04:31
yes that would be Jafar Hussain's approach (who is a rockstar imo)
well not approach but language
Chet Harrison
@ChetHarrison
Sep 10 2015 04:38
I have a use case in which I have a list of arbitrarily nested objects that need to be transformed into a new list. in order to avoid mutation, essentially a open ended dependency chain. I am just wondering if the composability of a state monad out strips a deep clone and mutation of the passed list arg.
Scott Christopher
@scott-christopher
Sep 10 2015 04:40
Not entirely sure I follow. Do you have some example code?
Chet Harrison
@ChetHarrison
Sep 10 2015 04:44
I don't blame you and I very much appreciate your help. I am trying to think of how to reduce the complexity of the example to it's simplest state
Chet Harrison
@ChetHarrison
Sep 10 2015 04:49
Well let's say this: from a perf standpoint it is probably simple enough to just run some tests and get the answer. But before I grab a monad from a lib (fantasyland, folktale, Monet) I would like to know if there is one with the "go to" api for the ramda community,
not that you have to take that on as a spokesperson for the "community" :smile:
Scott Christopher
@scott-christopher
Sep 10 2015 04:50
:D
Chet Harrison
@ChetHarrison
Sep 10 2015 04:51
dig it fo sho
Scott Christopher
@scott-christopher
Sep 10 2015 04:51
But it is lacking a state monad implementation
It is on my todo list at some stage
Chet Harrison
@ChetHarrison
Sep 10 2015 04:52
Well @scott-christopher It is a pleasure to meet you. Thanks for the feedback!
Scott Christopher
@scott-christopher
Sep 10 2015 04:52
You're welcome. Nice to meet you too.
Jethro Larson
@jethrolarson
Sep 10 2015 05:43
If you want proof that it works I've dumped it all in a jsbin https://jsbin.com/cevudu/edit?js,console
Jethro Larson
@jethrolarson
Sep 10 2015 05:49
Another neat benefit of skipping the prototype is that you can serialize from json without calling constructors. Well, that wont be true if you put functions in your containers but for flat values there's zero steps.
Raine Virta
@raine
Sep 10 2015 06:34
why does returning a curried function from compose break compose not handling optional arguments of the first function in the pipeline?
David Chambers
@davidchambers
Sep 10 2015 06:35
@raine, let's say the first function in the pipeline is JSON.parse, a function with one required argument and one optional argument.
Since we want to return a curried function from R.pipe (or R.compose), we need to look at the length of the first function in the pipeline to determine the arity of the function we return.
So R.pipe(JSON.parse, f, g, h) will return a curried binary function (regardless of the arities of f, g, and h).
But the author likely intended to get back a unary function.
The "solution" is to write R.pipe(R.identity, JSON.parse, f, g, h) instead.
Raine Virta
@raine
Sep 10 2015 06:45
or wrap JSON.parse with unary?
Jethro Larson
@jethrolarson
Sep 10 2015 06:56
@davidchambers SOLID is a series of principles for OOP. I know it's not all relevant, but if I'm selling FP to OOP people I need to at least have answers
Raine Virta
@raine
Sep 10 2015 06:56
and the alternative is to return a variadic function, as it used to be, right?
David Chambers
@davidchambers
Sep 10 2015 07:23
Correct on both counts, @raine.
Esa-Matti Suuronen
@epeli
Sep 10 2015 07:31
@CrossEye thanks for the explanation and useWith suggestion. Gitter should implement email notifications for mentions if I'm not active here. Totally missed your reply yesterday...
Denis Stoyanov
@xgrommx
Sep 10 2015 08:17
A big list of materials regarding FP and FRP https://github.com/gspindles/Papers
Scott Sauyet
@CrossEye
Sep 10 2015 12:04
@epeli: I don't remember how I set it up, but I do get email notifications from Gitter. As to compose, it looks as if discussions are becoming active again.
Raine Virta
@raine
Sep 10 2015 13:28
@davidchambers thanks for clearing that up
Raine Virta
@raine
Sep 10 2015 15:27
what do you call it when you go from [Either {k: v}] to Either [{k: v}]?
sequence?
Scott Sauyet
@CrossEye
Sep 10 2015 15:34
Drew
@dtipson
Sep 10 2015 15:54
Really enjoying exploring ramda. Random question: are there theoretical/practical reasons to prefer creating separate Lenses for each level down into an object (sort of like how makeLenses works) to work over some deep property/index like this: http://bit.ly/1KGDzKl vs just making a single lens that works on some deeper property directly, like this: http://bit.ly/1KGDk23 ?
Scott Sauyet
@CrossEye
Sep 10 2015 16:01
I think the main point idea is that lenses compose. So const xLens = R.lensProp('x'), zLens = R.lensProp('z') and you can just do compose(xLens, zLens) to get the desired behavior. But I'm still a novice with lenses, so don't quote me.
David Chambers
@davidchambers
Sep 10 2015 16:25
The nice thing about @CrossEye's approach is that the individual lenses may themselves be useful (xLens more so than zLens in this case). As a byproduct of describing a means of accessing or transforming .x.z one has done the same for .x (and .z).
Drew
@dtipson
Sep 10 2015 16:42
A lens with a deeper focus should still compose too though, right? http://bit.ly/1OD8gOg
David Chambers
@davidchambers
Sep 10 2015 16:57
Indeed. My point is that if you define your .x.y lens via R.lens(R.path(['x','y']), R.assocPath(['x','y'])) and later realize you want an .x lens as well, you won't have one on hand. Had you defined .x.y via composition of .x and .y, you'd already have an .x lens. :)
Jethro Larson
@jethrolarson
Sep 10 2015 17:08
I think lenses like pipe pieces in plumbing. They individually have a shape and you can put them together to get read/write on a substructure
Kinda lost the metaphor there
David Chambers
@davidchambers
Sep 10 2015 17:14
Haha!
Drew
@dtipson
Sep 10 2015 17:29
Gotcha. Just trying to get a sense of whether I'm missing something deeper in the theory of lenses that makes defining a several-level deep lens problematic. Agree that makeLenses is probably a more useful function for a library than shortcuts like lensPath or lensOverPath would be.
Need to make sure I get this before I try to wrap my head around zippers/cursors :)
David Chambers
@davidchambers
Sep 10 2015 17:37
I haven't learnt about zippers yet. There are still so many interesting concepts for me to learn!
Drew
@dtipson
Sep 10 2015 17:40
First read about them here: http://scienceblogs.com/goodmath/2010/01/13/zippers-making-functional-upda/ and then recently saw someone using cursors on a react project
David Chase
@davidchase
Sep 10 2015 18:11
i have a question about lenses as well http://bit.ly/1L4Ln7t, does it quickly without lenses, was wondering if its possible to do with lenses because i would like to return the full structure and does seem super clean
David Chambers
@davidchambers
Sep 10 2015 18:17
You want to update a substructure based on an unrelated substructure. Lenses don't seem like a good fit, because R.over does not provide the full data structure to the transformer. I imagine there's a related idea which applies in such cases.
David Chambers
@davidchambers
Sep 10 2015 18:24
You're hard-coding the index in that case though?
Jethro Larson
@jethrolarson
Sep 10 2015 18:25
David Chase
@davidchase
Sep 10 2015 18:26
yeah i do not want to hard code the index
since the update to the array is based off the selector property
Jethro Larson
@jethrolarson
Sep 10 2015 18:27
Obv that can be tightened up, but that gives you a lens that replaces the item in the array matching the selector
David Chase
@davidchase
Sep 10 2015 18:27
@davidchambers yeah i was just wishful thinking
David Chase
@davidchase
Sep 10 2015 18:34
@jethrolarson sorry how would you use that?
Drew
@dtipson
Sep 10 2015 18:51
Ah, I missed that part.
David Chase
@davidchase
Sep 10 2015 18:57
yeah sorry if it wasnt clear via the repl
Jethro Larson
@jethrolarson
Sep 10 2015 18:57
I was having trouble debuggin in repl so here on jsbin
https://jsbin.amazon.com/hobihaqoq/1/edit?js,console
R.over the list is of no help since you need to query the selector
David Chase
@davidchase
Sep 10 2015 19:01
that link doesnt work for me :(
Drew
@dtipson
Sep 10 2015 19:01
Right. Obviously possible to set it up so that it's dependent outside the implementation: http://bit.ly/1L4PHUd but that's not really a path to setting up a function that can just take "data" as a final argument
Jethro Larson
@jethrolarson
Sep 10 2015 19:03
yeah, there's a "Y" hidden in this problem
lenses are simple when they're linear
Drew
@dtipson
Sep 10 2015 19:06
yeah, when what you're focusing on isn't determined by some other part of what you're focusing on
Jethro Larson
@jethrolarson
Sep 10 2015 19:10
But even though this lens isn't pretty it's still composable with other lenses :)
I need to learn about prisms next
Drew
@dtipson
Sep 10 2015 19:11
is that actually a thing?!
Jethro Larson
@jethrolarson
Sep 10 2015 19:12
I saw a talk that touched on it. But now that I google I'm not sure
Apparently a video of a talk that will be given in June of next year :p
Jethro Larson
@jethrolarson
Sep 10 2015 19:30
hah. Interesting watch anyway. Prism is basically a Lens/Maybe mashup
David Chambers
@davidchambers
Sep 10 2015 19:32
Interesting! I'd been wondering whether that might be the case. @tel said as much in https://github.com/ramda/ramda/pull/1344#issuecomment-133253908, but I haven't yet understood the rest of his comment.
The current functions violate one of the lens laws, since R.set(lens, R.view(lens, x), x) is not equivalent to x if x is {}, for example.
If R.view(lens, x) gave Nothing() rather than undefined, and if R.set expected a Maybe, the result would be {} when x is {}.