These are chat archives for ramda/ramda

14th
Apr 2017
Tushar Mathur
@tusharmath
Apr 14 2017 05:51
@Bradcomp @skatcat31 Thanks ! This makes it a lot more intuitive.
Kurt Milam
@kurtmilam
Apr 14 2017 10:18
I'm stuck trying to get the following to work:
function makeObj( acc, list ) {
  const theTail = R.tail( list )
  const val = theTail.length > 0
    ? makeObj( acc, theTail )
    : {}
  return R.assoc( R.head( list ), val, {} )
}

R.reduce( makeObj, {} )( [ [ "a", "b" ], [ "a", "c" ] ] )
// current output { "a": { "c":  {} } }
// I want { "a":  { "b":  {}, "c":  {} } }
I know why it's not working, but my brain's letting me down when looking for the solution.
I felt like I was pretty close at 2AM last night, then the REPL I was working in froze up, and I hadn't saved my work :(
Denis Stoyanov
@xgrommx
Apr 14 2017 10:34
@kurtmilam ugly solution mergeWithKey((k,l,r) => k === 'a' && {[l]:{}, [r]:{}}, ...map(apply(objOf), [ [ "a", "b" ], [ "a", "c" ]]))
Kurt Milam
@kurtmilam
Apr 14 2017 10:40
Thanks. I'll need a solution that works with an arbitrary number of input arrays, each with an arbitrary number of keys.
I'll see whether I can use your solution as a basis for a more generalized solution.
Kurt Milam
@kurtmilam
Apr 14 2017 10:45
Looking for something that would work with the following input, as well:
[ [ "a", "b" ], [ "a", "c", "d" ], [ "e", "f" ] ] to output:
{ a: { b: {}
     , c: { d:{} }
     }
, e: { f:{} }
}
Kurt Milam
@kurtmilam
Apr 14 2017 11:08
@xgrommx The funny thing is that I wrote a little deep extend / deep merge mixin for lodash and underscore 5 years ago that would make this (and much more) an easy task, but it's imperative, and I'd like to figure out a way to do it in fp. It would be nice if ramda offered a deepExtend function.
Robert Mennell
@skatcat31
Apr 14 2017 16:02
the only problem: Over ridden. This means that you'll need to do sdome special handling to make sure that you nest correctly. assocPath seems to be almost exactly what you want except when it comes to marging(in which case you'd want to reccur)
@kurtmilam another issue with your code:val = theTail.length > 0 ? makeObj ( acc, theTail ) <- You passed the top level
which will again overwrite
Robert Mennell
@skatcat31
Apr 14 2017 16:08
What you should be passing it is acc[ R.head( list ) ] ? acc[ R.head( list ) ] : {}
@kurtmilam fixed: https://goo.gl/d3rBIi
// A fix of the provided code
function makeObj( acc, list ) {
  const theTail = R.tail( list )
  const val = theTail.length > 0
    ? acc[ R.head( list ) ]
    ? makeObj( acc[ R.head( list ) ], theTail )
    : makeObj( {}, theTail )
    : {}
  return R.assoc( R.head( list ), val, acc )
}

R.reduce( makeObj, {} )( [ [ "a", "b" ], [ "a", "c" ] ] )
// {"a": {"b": {}, "c": {}}}
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:16
Is it possible to make a regular function that returns a regular object pass for a class and instance?
const Foo = () => ({ })
const foo = new Foo()
foo instanceof Foo
I hate classes
but the spec requires this
Robert Mennell
@skatcat31
Apr 14 2017 16:16
You mean a factory?
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:17
I usually would call Foo a factory, yes. Just a regular function.
the new there was optional, of course.
Michael Rosata
@mrosata
Apr 14 2017 16:17
R.map(
    R.when(
      R.is(Array)
      , (p) => R.set(R.lensPath(p), {}, {})
    ))
That does what you want I think, but I just realized it's wrapped in an array, so you would have to unwrap it, and it only works on 2D arrays
Robert Mennell
@skatcat31
Apr 14 2017 16:21
a factory adapter in vanilla with manual currying
function Factory ( Foo ){
  return function( ...x ){
    return new Foo( ...x );
  }
}
const Factory = C => ...i => new C(...i)
Gabe Johnson
@gabejohnson
Apr 14 2017 16:23
@m59peacemaker which spec?
Robert Mennell
@skatcat31
Apr 14 2017 16:23
how is Factory not in Ramda?
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:23
I'm considering rewriting node-fetch.
because I'm a crazy person.
Michael Rosata
@mrosata
Apr 14 2017 16:23
there is the construct
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:24
It's a general problem. JS is class based and I'd rather not replicate JS classes with real classes.
fake it all the way :)
Robert Mennell
@skatcat31
Apr 14 2017 16:25
@mrosata they couldn't call it factory why?
Gabe Johnson
@gabejohnson
Apr 14 2017 16:25
@skatcat31 b/c factory is an OO pattern?
and this is an FP lib
Robert Mennell
@skatcat31
Apr 14 2017 16:26
omfg... constructN.... I swear to god if the reason it comes down to it wasn't for the pun of constructioN...
module.exports = _curry2(function constructN(n, Fn) {
  if (n > 10) {
    throw new Error('Constructor with greater than ten arguments');
  }
  if (n === 0) {
    return function() { return new Fn(); };
  }
  return curry(nAry(n, function($0, $1, $2, $3, $4, $5, $6, $7, $8, $9) {
    switch (arguments.length) {
      case  1: return new Fn($0);
      case  2: ...
    }
  }));
});
so in essence they did the same thing I did.. curry a Factory adaptor...
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:28
I might have found a decent way to go, but this is what I was referring to (this doesn't work, of course)
function Foo () { return {} }
R.construct(Foo)() instanceof Foo
I think I have to deal with the class stuff at some point. No way to fake it.
Robert Mennell
@skatcat31
Apr 14 2017 16:31
@m59peacemaker https://goo.gl/0WdvUp
Brad Compton (he/him)
@Bradcomp
Apr 14 2017 16:33
Factory pretty much does the same thing as R.construct
Gabe Johnson
@gabejohnson
Apr 14 2017 16:33
var Foo = () => ({ constructor: Foo });
Foo.prototype = Object.prototype;
Foo() instanceof Foo // true
Michael Rosata
@mrosata
Apr 14 2017 16:33
@skatcat31 not sure, maybe they thought "construct" would read a bit more expressively. The code construct(House) might read outloud as "construct a house". Just a guess though. I actually didn't know about construct until very recently myself
Robert Mennell
@skatcat31
Apr 14 2017 16:34
@Bradcomp almost exactly. The difference I wanted to show was that Foo in my code return this
@m59peacemaker your Foo function is a base Object factory. Return this
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:34
I'm not really following man. This works for me, though
const Foo = () => {
  return Object.create(Object.assign(Foo.prototype, {

  }))  
}
Foo() instanceof Foo
Returning this would defeat the whole idea. Then I have to load up this
with properties
Brad Compton (he/him)
@Bradcomp
Apr 14 2017 16:36
I was gonna mention Object.crteate
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:36
@skatcat31 Just to clarify - are we on the same page about how I want to do as little class/this stuff as possible?
I have it all done without anything like that, except the instanceof check won't pass
Robert Mennell
@skatcat31
Apr 14 2017 16:37
@m59peacemaker I think I might be missing something
Michael Rosata
@mrosata
Apr 14 2017 16:37
I think @skatcat31 is saying that the Foo implementation would break the prototype chain if you were inheriting more than 1 level. Right?
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:37
so, I wan't to take otherwise plain function that returns an object and make the object an instance of the function
I'm not inheriting anything :)
Robert Mennell
@skatcat31
Apr 14 2017 16:38
@m59peacemaker okay so you want to make a Functory that assigns a function to a prototype?
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:38
const Foo = () => ({ hey: () => 'hello' })
Foo() instanceof Foo
so, if you had that exact code
and you just want that to be true
As simple as that
You don't want to go making classes or assigning things to prototypes
but you just want it to look like you did
because JS is silly like that
Gabe Johnson
@gabejohnson
Apr 14 2017 16:39
@m59peacemaker :point_up: April 14, 2017 11:33 AM
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:40
ah! I didn't see that!
Michael Rosata
@mrosata
Apr 14 2017 16:41
@gabejohnson that is clever
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:41
that doesn't have any other side effects?
Gabe Johnson
@gabejohnson
Apr 14 2017 16:43
probably
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:43
I don't think it would... sounds pretty solid.
oh hah
Gabe Johnson
@gabejohnson
Apr 14 2017 16:43
I just thought it up. Never used it
Robert Mennell
@skatcat31
Apr 14 2017 16:44
@m59peacemaker I think I'd be with @Bradcomp with Object.create
Michael Rosata
@mrosata
Apr 14 2017 16:44
const Foo = () => ({ constructor: Foo, prototype: Object.prototype }) wouldn't that be better? @gabejohnson
or by better, I mean the same?
Gabe Johnson
@gabejohnson
Apr 14 2017 16:45
@mrosata no. you don't want prototype on the object itself
Michael Rosata
@mrosata
Apr 14 2017 16:45
ahh yes
gotcha
Gabe Johnson
@gabejohnson
Apr 14 2017 16:49
To be fair, I probably thought that up because I've been reading a lot of code from those two projects and Sanctuary. Something similar might be used in one of those
Johnny Hauser
@m59peacemaker
Apr 14 2017 16:52
lol brains
now everytime I got to the project, I'm writing Foo instead of the actual function name
  const headers = Object.assign(Object.create(Headers.prototype), {
    ... etc
  })
is how I'm going to roll
but the other thing is clever. Thanks for the nolege.
Michael Rosata
@mrosata
Apr 14 2017 16:59
@m59peacemaker The only thing that could be a problem with your const headers = Object.assign is that headers are supposed to be immutable and yours wouldn't be immutable out the box. I don't even know if that would cause problems or not. Just an observation
Johnny Hauser
@m59peacemaker
Apr 14 2017 17:00
fetch api headers?
Michael Rosata
@mrosata
Apr 14 2017 17:00
yea
Johnny Hauser
@m59peacemaker
Apr 14 2017 17:00
I haven't seen anything about that
Are you talking about the guard setting under the conditions that it is supposed to be 'immutable' ?
Michael Rosata
@mrosata
Apr 14 2017 17:04
possibly. I'd have to look it up to be honest. I thought I remembered reading something about the Headers not being able to be changed after creation. Maybe it's not so, but I figured it might be something worth noting (if it's even true I suppose)
Robert Mennell
@skatcat31
Apr 14 2017 17:05
Pretty sure the only time you can't chagne a header is after it's sent...
Michael Rosata
@mrosata
Apr 14 2017 17:05
unless your the man in the middle :smile:
Maybe I have it wrong about the headers though
Johnny Hauser
@m59peacemaker
Apr 14 2017 17:06
nah man, go in your console and do
  var x = new Headers({ a: 1 })
  x.set('a', 2)
  x.get('a') // '2'
I think you're talking about guard. node-fetch doesn't even have that.
Michael Rosata
@mrosata
Apr 14 2017 17:07
I think I'm thinking about the actual Request object having readonly attributes
Johnny Hauser
@m59peacemaker
Apr 14 2017 17:07
Yeah
That's one of the conditions where guard is suppose to be immutable
Michael Rosata
@mrosata
Apr 14 2017 17:09
I'll read the link you sent after I eat lunch
thx @m59peacemaker
Kurt Milam
@kurtmilam
Apr 14 2017 18:33
@skatcat31 that looks good, thanks! One note in case anyone comes across it and wants to work with it: If you have lists of different lengths, you need to process the lists in order from shortest to longest to make sure nothing gets overwritten.
IOW:
R.reduce( makeObj, {} )( [ [ 'a' ], [ 'a', 'b' ] ] ) // -> { a: { b: {} } }
// but
R.reduce( makeObj, {} )( [ [ 'a', 'b' ], [ 'a' ] ] ) // -> { a: {} }
Robert Mennell
@skatcat31
Apr 14 2017 18:38
@kurtmilam reduce( makeObj, {} ) ( sortBy ( length , arrays ) ) https://goo.gl/3vNjef
Kurt Milam
@kurtmilam
Apr 14 2017 18:38
Exactly my plan - just wanted to drop the fyi in case anyone else stumbled across it and found it useful. Thanks again!
Robert Mennell
@skatcat31
Apr 14 2017 18:44
@kurtmilam baked in: https://goo.gl/3vNjef
// A fix of the provided code
function makeO( acc, list ) {
  const theTail = R.tail( list )
  const val = theTail.length > 0
    ? acc[ R.head( list ) ]
    ? makeO( acc[ R.head( list ) ], theTail )
    : makeO( {}, theTail )
    : {}
  return R.assoc( R.head( list ), val, acc )
}

const makeObj = arrs => R.reduce( makeO, {} )( sortBy( length, arrs ) )
makeObj([ [ "a", "b", 'c' ], [ "a", "c" ] ])
// {"a": {"b": {"c": {}}, "c": {}}}
Kurt Milam
@kurtmilam
Apr 14 2017 18:49
:thumbsup:
Robert Mennell
@skatcat31
Apr 14 2017 19:21
@kurtmilam An interesting change would be testing for a String/symbol and if it's not a string or symbol, instead just it for the value
Kurt Milam
@kurtmilam
Apr 14 2017 19:27
:thumbsup:
In my current use case they'll either all be strings or the last element will be a function.
Haven't decided yet.
Jonah
@jonahx
Apr 14 2017 20:37
I am writing a “power” function that is the xprod applied n times. I have:
@ram-bot
const nthXprod = (arr, n) =>
  R.reduce(R.pipe(R.xprod, R.map(R.unnest)), arr, R.repeat(arr, n-1))

console.log( nthXprod([1,2], 3) )

which produces (since i suck at ram-bot, apparently):

[ [ 1, 1, 1 ],
  [ 1, 1, 2 ],
  [ 1, 2, 1 ],
  [ 1, 2, 2 ],
  [ 2, 1, 1 ],
  [ 2, 1, 2 ],
  [ 2, 2, 1 ],
  [ 2, 2, 2 ] ]

Looking for improvement suggestions on the function def

Robert Mennell
@skatcat31
Apr 14 2017 20:38
@jonahx nah Rambot is just offline ATM
Jonah
@jonahx
Apr 14 2017 20:40
specifically, i suspect there’s a better way to do the map nest part
Denis Stoyanov
@xgrommx
Apr 14 2017 20:41
@jonahx what is your goal?
Robert Mennell
@skatcat31
Apr 14 2017 20:42
@xgrommx weren't we talking about this yesterday as an applicative?
Jonah
@jonahx
Apr 14 2017 20:43
@xgrommx i suppose you could think of it as all possible strings of length of n, where the alphabet is defined by the array members. i think the example above should clarify, lmk if you want more tho
Denis Stoyanov
@xgrommx
Apr 14 2017 20:43
@jonahx sequence(of, repeat([1,2], 3))
@skatcat31 yes, I told about sequence, filterM, etc :smile:
Robert Mennell
@skatcat31
Apr 14 2017 20:45
@xgrommx was actually trying to tag you in this conversation... I see you replied to @jonahx as I was typing the tag XD
Jonah
@jonahx
Apr 14 2017 20:45
@xgrommx exactly what i wanted. ty, sir.
i need to incorporate sequence, ap, lift, etc more thouroughly into my mental model
Denis Stoyanov
@xgrommx
Apr 14 2017 20:47
@jonahx scroll up, we have discussion with @skatcat31 about applicative and other stuff
Jonah
@jonahx
Apr 14 2017 20:47
@xgrommx will do, thx
Robert Mennell
@skatcat31
Apr 14 2017 20:48
@jonahx :point_up: April 13, 2017 11:09 AM
Denis Stoyanov
@xgrommx
Apr 14 2017 20:48
@jonahx try this compose(map(flatten), traverse(of, x => [x, []]))([1,2,3])
@jonahx and explain for me what going on ;)
Jonah
@jonahx
Apr 14 2017 20:49
@xgrommx gimme a few :) need to make coffee
Robert Mennell
@skatcat31
Apr 14 2017 20:49
compose(map(flatten), traverse(of, x => [x, 'a']))([1,2,3]) ended up explaining it a bit better to me
Denis Stoyanov
@xgrommx
Apr 14 2017 20:49
@jonahx ok, why traverse(of, x => [x, x * x])([1,2,3]) got 8 effects?
@skatcat31 doesn't matter =)
m(t a) -> t(m a) m <- functor law, t <- applicative effect :smile:
sequence [Just 10, Just 20] we have 2 elements of Maybe
after sequence we got Just [10, 20]
we still have 2 elements and applicative effect from Maybe
Denis Stoyanov
@xgrommx
Apr 14 2017 20:57
doesn't matter which are elements contains in array, we have 2 elements and we need to get 2 elements (from law of functor)
+ effect of applicative functor
I think it was explainable)
Robert Mennell
@skatcat31
Apr 14 2017 20:59
wait... isn't the x => [x, x*x] returning an array?
Denis Stoyanov
@xgrommx
Apr 14 2017 21:00
@skatcat31 try to write it in types
@skatcat31 [[a]] -> [[a]]
@skatcat31 Maybe [a] -> [Maybe a]
Robert Mennell
@skatcat31
Apr 14 2017 21:05
@xgrommx okay I'll type types: wait isn't the second function passed to traverse of type a -> [a]?
... wait... no now I'm more confused
Denis Stoyanov
@xgrommx
Apr 14 2017 21:06
@skatcat31 yes, traverse(of, x => [x, x*x])([1,2,3])
@skatcat31 traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
(a -> b) -> t a -> t b is functor
only if u will to use Identity
because Identity doesn't have some effect
and we can derive fmap fromtraverse
Jonah
@jonahx
Apr 14 2017 21:11

@xgrommx, ok before answering your question (which i understand what’s going on there, but don’t understand deeply why), i still don’t really get why the ap results in a cross product. ie:

  R.ap([x=>x*x, x=>x+x], [1,2, 3,4])
// [ 1, 4, 9, 16, 2, 4, 6, 8 ]

Is it just the only reasonable way an array can made into an Apply and still follow the rules of that algebraic structure?

Robert Mennell
@skatcat31
Apr 14 2017 21:12
wait so it's creating 3 arrays by passing each element to the functor, and then zipping them with the first functor?
Denis Stoyanov
@xgrommx
Apr 14 2017 21:14
@jonahx this is normal case Cartesian product
@jonahx array has 2 applicative effect. Cartesian product (each with other) and like zip (pair)
Jonah
@jonahx
Apr 14 2017 21:16
@xgrommx what’s an example where both effects may be seen simultaneously?
Denis Stoyanov
@xgrommx
Apr 14 2017 21:16
@jonahx first u provided me above
Jonah
@jonahx
Apr 14 2017 21:18
@xgrommx do you mean this example: R.ap([x=>x*x, x=>x+x], [1,2, 3,4])? i see the cartesian product effect here, where is the zip effect?
Jonah
@jonahx
Apr 14 2017 21:21
@xgrommx sorry i meant in my simple example: R.ap([x=>x*x, x=>x+x], [1,2, 3,4])
Denis Stoyanov
@xgrommx
Apr 14 2017 21:23
@jonahx cartesian product -> lift((a, b) => [a, b])([1,2,3], [4,5,6])
Jonah
@jonahx
Apr 14 2017 21:28
@xgrommx i understand the examples, but feel i’m missing a deeper understanding of why ap works that way for lists. maybe the answer is just “because that definition satisfies the Apply laws”?
Denis Stoyanov
@xgrommx
Apr 14 2017 21:31
@jonahx f (a -> b) -> f a -> f b we need extract all values from f a and extract all functions from f (a -> b) and apply each with other, then pack it in f (f b)
Brad Compton (he/him)
@Bradcomp
Apr 14 2017 21:32
There are multiple valid apply instances for list, this just happens to be the one Ramda chose to implement
Denis Stoyanov
@xgrommx
Apr 14 2017 21:32
@Bradcomp this is default version for FP realization it isn't Ramda choice
Brad Compton (he/him)
@Bradcomp
Apr 14 2017 21:33
Good to know
Jonah
@jonahx
Apr 14 2017 21:33
@Bradcomp @xgrommx what is another possible definition for list Apply?
Brad Compton (he/him)
@Bradcomp
Apr 14 2017 21:33
Here's one:
instance Applicative Vector where
  pure a = Vector (repeat a)
  (<*>) (Vector f) (Vector v) = Vector $ zipWith ($) f v
:point_up: Vector in this case is implemented as a list
Denis Stoyanov
@xgrommx
Apr 14 2017 21:34
Brad Compton (he/him)
@Bradcomp
Apr 14 2017 21:34
From a linear algebra library I was messing with
Jonah
@jonahx
Apr 14 2017 21:36
@xgrommx my bad, wasn’t putting the 2 things together. thx guys, i’m going to delve into this a bit more on my own
Denis Stoyanov
@xgrommx
Apr 14 2017 21:36
@Bradcomp u don't need it. In Control.Applicative exists ZipList
Brad Compton (he/him)
@Bradcomp
Apr 14 2017 21:37
Sure, but I'm a relative Haskell n00b, and it was a good exercise
Jonah
@jonahx
Apr 14 2017 21:42
@xgrommx @Bradcomp do you have a favorite haskell book?
Denis Stoyanov
@xgrommx
Apr 14 2017 21:43
@jonahx yes
Jonah
@jonahx
Apr 14 2017 21:44
@xgrommx thoughts on graham hutton’s book? i’ve heard that’s good from a few people
Brad Compton (he/him)
@Bradcomp
Apr 14 2017 21:46
I hear the Haskell Book is really good but I haven't read it. I've mainly relied on the tutorials and googling approach