These are chat archives for ramda/ramda

22nd
Apr 2016
Martin Broder
@mrtnbroder
Apr 22 2016 14:30

Question, this is foldl from Elm:

foldl : (a -> b -> b) -> b -> List a -> b

and this from ramda:
reduce: ((a, b) → a) → a → [b] → a

now I'm a bit lost. They do the same thing, no?

Drew
@dtipson
Apr 22 2016 14:32
does the reducing function part of the Elm version just take the item first and the accumulated result second?
Martin Broder
@mrtnbroder
Apr 22 2016 14:32
yeah it looks like its flipped
Jakub Korzeniowski
@kujon
Apr 22 2016 14:33
Quick question: what's the lowest, most pathetic browser ramda will still work in?
Hardy Jones
@joneshf
Apr 22 2016 14:38
@mrtnbroder you can alpha rename the variables to make it clearer
Martin Broder
@mrtnbroder
Apr 22 2016 14:39
hm?
Hardy Jones
@joneshf
Apr 22 2016 14:39
foldl : (elem -> accum -> accum) -> accum -> List elem -> accum
vs.
reduce : ((accum, elem) -> accum) -> accum -> [elem] -> accum
alpha rename is basically, replace all variables of the same name, with a different name.
So in foldl we alpha renamed a => elem and b => accum. In reduce we alpha renamed a => accum and b => elem
Nothing has changed aside from the name of each type variable being used. Hopefully, this makes the types easier to understand.
there's nothing special about a, b, elem, or accum.
Hardy Jones
@joneshf
Apr 22 2016 14:46
the List a vs [a] thing is syntactic, so those parts are equivalent.
then it's just the first argument
elem -> accum -> accum should be equivalent to (accum, elem) -> accum for reasons that might complect the explanation.
Martin Broder
@mrtnbroder
Apr 22 2016 14:49
yes
makes sense :)
Hardy Jones
@joneshf
Apr 22 2016 14:49
Given that we have a concrete list/array type in the signature, "probably" is the answer to your original question. Without running tests or just looking at the implementation, that's about as good an answer you can get.
Now, given that both of these functions have been used by multiple people for a long time, and given the people/communities around them, I'd say "almost assuredly" is a more realistic answer. But, that doesn't really follow logically since I'm appealing to authority and appealing to majority. So take it for what it's worth.
Martin Broder
@mrtnbroder
Apr 22 2016 15:00
wat
lol jk. I guess what @dtipson said is true
it's taking the item first and then the accumulated value
Martin Broder
@mrtnbroder
Apr 22 2016 15:10
thanks @joneshf
Drew
@dtipson
Apr 22 2016 19:02
what order arguments should be in can be something of a judgement call, even in FP where we want configuration first and target data last
I'd certainly argue that in a reducing function, accumulator is configuration and each item is data, but I might also be missing some idiom or pattern Elm uses that supports the reverse
Jonah
@jonahx
Apr 22 2016 19:23
Anyone know a good way to validate that an object has the same structure as another object? I could use https://github.com/Nijikokun/generate-schema to generate a schema object, and then something like https://github.com/geraintluff/tv4 to validate another object against that schema. Is there a better way?
Jonah
@jonahx
Apr 22 2016 20:06
perhaps i should just use function like this:
function sameStructure(o1, o2) {
  var o1Type = typeof(o1),
      o2Type = typeof(o2);
  return (o1Type != o2Type)   ? false :
         (o1Type != 'object') ? true  :
         Object.keys(o1).every(k => 
           o2.hasOwnProperty(k) 
           && typeof(o1[k]) == typeof(o2[k])
           && ( typeof(o1[k]) == 'object' ? sameStructure(o1[k], o2[k]) : true )
         )
}
Risto Stevcev
@Risto-Stevcev
Apr 22 2016 21:30
@jonahx Nice, I think that you should propose that as a function for ramda :)
I think it's a common enough situation to warrant being in a utility lib
Jonah
@jonahx
Apr 22 2016 21:36
@Risto-Stevcev thanks. probably needs to be examined more for edge cases. So far, I’ve updated to:
function sameStructure(o1, o2) {
  var o1Type = o1.constructor,
      o2Type = o2.constructor;

  return (o1Type != o2Type) ? false :
         (o1Type != Object) ? true  :
         sameKeys(o1, o2) 
         && Object.keys(o1).every(k => sameStructure(o1[k], o2[k]))

  function sameKeys(o1, o2) {
    var o1Keys = Object.keys(o1),
        o2Keys = Object.keys(o2);
     return o1Keys.length == o2Keys.length &&
            o1Keys.every((v,i)=> v === o2Keys[i]);
  }
}

test('sameStructure', function (t) {
  var o1 = {a: 1, b: "asdf", c: []},
      o2 = {a: 9, b: "xxx", c: [1,2]};
      o3 = {a: "a", b: "xxx", c: [1,2]};
      o4 = {b: "asdf", c: []},
      o5 = {a: {a: 1, b:[]}, b: "xxx"}
      o6 = {a: {a: 2, b:[9]}, b: "yyy"}
      o7 = {a: {a: 2, b:'yo'}, b: "yyy"}
  t.true (sameStructure(o1, o2), 'Same flat structure')
  t.false(sameStructure(o1, o3), 'Different type 1 level deep')
  t.false(sameStructure(o1, o4), 'o2 missing one key')
  t.false(sameStructure(o4, o1), 'o1 missing one key')
  t.true (sameStructure(o5, o6), 'Same nested structure')
  t.false(sameStructure(o5, o7), 'Different type 2 levels deep')
  t.end()
})
And could be shortened up quite a bit with ramda functions, but I was trying to keep in dependency free for my current purposes
hozkok
@hozkok
Apr 22 2016 22:21
great code @jonahx . brilliant.