These are chat archives for ramda/ramda

20th
May 2017
Denis Stoyanov
@xgrommx
May 20 2017 01:41
@ram-bot
const filterM = (of, p) => reduceRight((x, acc) => liftN(2, (flg, v) => flg ? [x, ...v] : v)(p(x), acc), of([]));

const subsequences = compose(reverse, filterM(of, always([true, false])))

const insertEverywhere = x => xs => {
  if(xs.length) {
    const [y, ...ys] = xs
    return [[x, ...xs], ...map(v => [y, ...v], insertEverywhere(x)(ys))]
  } else return [[x]]
}

const permutations = reduceRight((x, xs) => chain(v => insertEverywhere(x)(v))(xs), [[]])

const choices = composeK(permutations, subsequences)

choices([1,2,3])
ram-bot
@ram-bot
May 20 2017 01:41
[ [],
  [ 3 ],
  [ 2 ],
  [ 2, 3 ],
  [ 3, 2 ],
  [ 1 ],
  [ 1, 3 ],
  [ 3, 1 ],
  [ 1, 2 ],
  [ 2, 1 ],
  [ 1, 2, 3 ],
  [ 2, 1, 3 ],
  [ 2, 3, 1 ],
  [ 1, 3, 2 ],
  [ 3, 1, 2 ],
  [ 3, 2, 1 ] ]
Denis Stoyanov
@xgrommx
May 20 2017 01:41
nice
Michael Rosata
@mrosata
May 20 2017 03:10
@xgrommx you broke my R.head with that one. I can follow insertEverywhere, that's very cool. I understand what subsequences is doing but haven't yet wrapped my head around how. I get a bit lost with how filterM works, I might need to work filterM out on paper one day. I like trying to solve these though. I really just got my head wrapped around stuff like liftN(3, (a,b,c) => `${ a } ${ b } ${ c }`)(['hi', 'hello'], ['there', 'ole'], ['buddy', 'pal'])
Denis Stoyanov
@xgrommx
May 20 2017 04:04
@mrosata we had talk about filterM, traverse and etc earlier
Denis Stoyanov
@xgrommx
May 20 2017 04:19
:point_up: April 13, 2017 9:44 PM @mrosata
Vadim Nekrasov
@barbiturat
May 20 2017 08:05

How to realize currying by a condition?
For example, I want to create a function, which returns curried itself until sum of passed arguments equal 10.
Example:

// curryMaker(condition);
// “getResult" should return curried itself until sum of passed arguments equals 10.
const getResult = curryMaker((arg) => arg < 10);
getResult(5)(3)(2); // => 10

Can ramda be usefull for this goal?

Tushar Mathur
@tusharmath
May 20 2017 08:29
essentially you want to do recursion if I am not wrong @barbiturat ?
Vadim Nekrasov
@barbiturat
May 20 2017 08:51
@tusharmath I wanted to avoid a browser’s “scope depth” restriction
Because number of calls can be arbitrarily large
Vadim Nekrasov
@barbiturat
May 20 2017 09:03
recursive calls increase scope depth in each call
Galileo Sanchez
@galileopy
May 20 2017 12:45
@barbiturat and what should it return if the predicate is false?
Galileo Sanchez
@galileopy
May 20 2017 12:50
const { curry, ifElse, always, apply, compose}
const thing = curry((r, p) => function _fn (...args ){ 
       return ifElse(apply(compose(p, r)), always(_fn), apply(r))(args)
})
Michael Rosata
@mrosata
May 20 2017 12:51
@barbiturat I don't think there's anything that does that in Ramda. I can't think of something that would create a function with an unknown arity. I was thinking something like what @galipeopy wrote
const curryMaker = (pred, reducer) => (...args) => {
  const current = reducer(args)
  return pred(current) ? current : next => curryMaker(pred, reducer)(...args, next)
}

const a = curryMaker(R.lt(__, 10), reduce(R.add, 0))
a(29)(-10)(-9)(-1)
@xgrommx I will go find that convo and read it. Thank you
Galileo Sanchez
@galileopy
May 20 2017 12:53
however both use recursion @barbiturat , and @mrosata is more accurate since it takes care of remembering the last result
actually I think you can't avoid recursion here @barbiturat, you probably want to review your api and use cases and see if the interface you want is really necessary, or if your willing to compromise between recursion and easy of use
Michael Rosata
@mrosata
May 20 2017 13:07
@galileopy might be correct. Even if you wrote a function that wasn't directly recursive, it would still likely be returning a closure of a closure of a closure.
I feel like TCO has been OTW for about as long as I've been writing JavaScript. It must be right around the corner
Brian McKenna
@puffnfresh
May 20 2017 13:08
V8 has it right?
under a flag
Michael Rosata
@mrosata
May 20 2017 13:11
possibly. I will look it up
Brian McKenna
@puffnfresh
May 20 2017 13:16
$ node --harmony_tailcalls --use_strict
> function go(n) { return go(n + 1); }; go(0)
loops forever, no stack overflow :)
Michael Rosata
@mrosata
May 20 2017 13:25
yea, that
is nice :)
I just took it for a spin
Vadim Nekrasov
@barbiturat
May 20 2017 14:00
@galileopy , @mrosata Thank you!
Michael Rosata
@mrosata
May 20 2017 14:01
@barbiturat :smile:
Denis Stoyanov
@xgrommx
May 20 2017 15:15
@mrosata welcome =)
Michael Rosata
@mrosata
May 20 2017 15:18
@xgrommx Was the convo you mentioned from last month w/ @skatcat31 ? I remember that convo, I had https://kai-sassnowski.com/posts/understanding-filterm open in a browser tab for almost a week before closing it w/o reading
right now I'm almost to the bottom though, got my filterM implementation in Haskell working and most dissected
Denis Stoyanov
@xgrommx
May 20 2017 15:20
@mrosata what?)
Michael Rosata
@mrosata
May 20 2017 15:22
you said that there was a convo about traverse and filterM from earlier :point_up:, but I didn't find anything. So I assumed you meant the convo from last month
Denis Stoyanov
@xgrommx
May 20 2017 15:23
@mrosata what is convo?
Michael Rosata
@mrosata
May 20 2017 15:23
conversation
I think you had just solved for (or was looking for a solution to) "Given a list of integers, produce a list of all possible sums that can be created using the integers from the list" using Ramda and dropped that link to the explanation of that problem and the inner workings of filterM
Denis Stoyanov
@xgrommx
May 20 2017 15:26
@mrosata do u need this code?)
Michael Rosata
@mrosata
May 20 2017 15:27
not particularly
Denis Stoyanov
@xgrommx
May 20 2017 15:27
=)
Michael Rosata
@mrosata
May 20 2017 15:28
you could use your filterM from yesterday right? R.compose(R.map(R.sum), filterM(R.always([1, 0]))
something like that right?
Denis Stoyanov
@xgrommx
May 20 2017 15:30
@mrosata filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a]
predicate should return boolean which should be wrapped in monad
@mrosata powerSet = filterM(const [True, False])
Michael Rosata
@mrosata
May 20 2017 15:31
1 and 0 won't work for the predicate?
Denis Stoyanov
@xgrommx
May 20 2017 15:31
no
@mrosata only Boolean
Michael Rosata
@mrosata
May 20 2017 15:32
That's good to know. I've wanted to try this for some time, flying close to the sun here because I don't know if this will work:
@ram-bot
const filterM = (of, p) => reduceRight((x, acc) => liftN(2, (flg, v) => flg ? [x, ...v] : v)(p(x), acc), of([]));
R.compose(R.map(R.sum), filterM(of, R.always([true, false])))([1, 2, 3, 4, 5])
damn you @ram-bot
how do I make @ram-bot evaluate something?
Denis Stoyanov
@xgrommx
May 20 2017 15:34
@mrosata R.compose(R.map(R.sum), filterM(of, R.always([true, false])))([1, 2, 3, 4, 5]) u have errors
Michael Rosata
@mrosata
May 20 2017 15:35
would it have evaluated otherwise?
Denis Stoyanov
@xgrommx
May 20 2017 15:35
@ram-bot
const filterM = (of, p) => reduceRight((x, acc) => liftN(2, (flg, v) => flg ? [x, ...v] : v)(p(x), acc), of([]))
R.compose(R.map(R.sum), filterM(of, R.always([true, false])))([1, 2, 3, 4, 5])
ram-bot
@ram-bot
May 20 2017 15:35
[ 15,
  10,
  11,
  6,
  12,
  7,
  8,
  3,
  13,
  8,
  9,
  4,
  10,
  5,
  6,
  1,
  14,
  9,
  10,
  5,
  11,
  6,
  7,
  2,
  12,
  7,
  8,
  3,
  9,
  4,
  5,
  0 ]
Michael Rosata
@mrosata
May 20 2017 15:36
nice
Denis Stoyanov
@xgrommx
May 20 2017 15:37
Also I derive alternative for powerSet
@ram-bot
const powerSet = reduceRight((x, a) => ap(concat, map(prepend(x)))(a), [[]])
compose(map(sum), powerSet)([1, 2, 3, 4, 5])
ram-bot
@ram-bot
May 20 2017 15:37
[ 0,
  5,
  4,
  9,
  3,
  8,
  7,
  12,
  2,
  7,
  6,
  11,
  5,
  10,
  9,
  14,
  1,
  6,
  5,
  10,
  4,
  9,
  8,
  13,
  3,
  8,
  7,
  12,
  6,
  11,
  10,
  15 ]
Denis Stoyanov
@xgrommx
May 20 2017 15:39
@mrosata welcome =)
Michael Rosata
@mrosata
May 20 2017 15:39
thanks
powerSet is doing something similar to lift2 right?
Denis Stoyanov
@xgrommx
May 20 2017 15:41
@mrosata almost, as u can see I don't use filterM
@mrosata filterM more powerful
@ram-bot
const powerSet2  = compose(map(flatten), traverse(of, x => [x, []]))
compose(map(sum), powerSet2)([1, 2, 3, 4, 5])
ram-bot
@ram-bot
May 20 2017 15:41
[ 15,
  10,
  11,
  6,
  12,
  7,
  8,
  3,
  13,
  8,
  9,
  4,
  10,
  5,
  6,
  1,
  14,
  9,
  10,
  5,
  11,
  6,
  7,
  2,
  12,
  7,
  8,
  3,
  9,
  4,
  5,
  0 ]
Denis Stoyanov
@xgrommx
May 20 2017 15:42
@mrosata or const powerSet2 = compose(map(filter(Boolean)), traverse(of, x => [x, undefined]))
Bijoy Thomas
@bijoythomas
May 20 2017 15:44
@xgrommx I see in your earlier usage of max product of 3 elements as well as in your powerSet implementation, you are using ap without a list of functions as in ap(flip(objOf), product)([2,3,4])
Denis Stoyanov
@xgrommx
May 20 2017 15:45
@ram-bot
traverse(of, x => [x, undefined])([1,2,3])
ram-bot
@ram-bot
May 20 2017 15:45
[ [ 1, 2, 3 ],
  [ 1, 2, undefined ],
  [ 1, undefined, 3 ],
  [ 1, undefined, undefined ],
  [ undefined, 2, 3 ],
  [ undefined, 2, undefined ],
  [ undefined, undefined, 3 ],
  [ undefined, undefined, undefined ] ]
Bijoy Thomas
@bijoythomas
May 20 2017 15:45
how is ap working here with functions as args instead of an array of functions?
Denis Stoyanov
@xgrommx
May 20 2017 15:45
@bijoythomas applicative version for function
@bijoythomas S = f => g => x => f(x)(g(x))
@bijoythomas do u understand it?)
Bijoy Thomas
@bijoythomas
May 20 2017 15:50
I've used mostly lift so I understand lift(inc)(Just(5)) and I would have written the ap(flip(objOf), product)([2,3,4]) as lift(objOf)(product)(identity)([2,3,4]) .. but no .. sorry .. I don't understand your ap usage
Denis Stoyanov
@xgrommx
May 20 2017 15:51
@bijoythomas lift(inc)(Just 5) => map(inc)(Just 5)
Bijoy Thomas
@bijoythomas
May 20 2017 15:52
right .. so that's just the functor map right?
Denis Stoyanov
@xgrommx
May 20 2017 15:52
@bijoythomas in my case - no
@bijoythomas ap(flip(objOf), product) => ap = f => g => x => f(x)(g(x)) => f = flip(objOf), g = product => (flip(objOf)(x))(product(x)) => objOf(product(x), x)
Bijoy Thomas
@bijoythomas
May 20 2017 15:55
yes .. I see how when substituting in the equations .. it does make sense
lift(objOf)(product)(identity) is equal to objOf(product(x), x) also .. yes? .. is there a reason to use one over the other? what is there is more than one argument?
Denis Stoyanov
@xgrommx
May 20 2017 15:58
@bijoythomas strange using for lift
Bijoy Thomas
@bijoythomas
May 20 2017 15:59
@xgrommx yes .. I think my understanding of lift has me using it in places where it's not really meant to be used
Tom Harding
@i-am-tom
May 20 2017 17:03
Go for the latter in most cases. The former works because Function is an applicative - this particular pattern also gets called the S combinator in other places. There are some really neat examples (e.g. average = lift(divide, sum, length) but I’d restrict your usage to situations where it almost reads as its implementation (e.g. “average = divide sum (by) length”)
Bijoy Thomas
@bijoythomas
May 20 2017 17:23
Thanks @xgrommx and @i-am-tom
I didn't know that was the S combinator
Bijoy Thomas
@bijoythomas
May 20 2017 20:33
Ok .. took a break and went back to LYAH and I think I got my fp aha moment today w.r.t functions as applicatives :-) .. so for applicatives, we need to extract a function in a 'Box' and apply it to a value in a 'Box' for the type (-> r) we need a function from r to extract a function, and another function from r to extract the value and apply the extracted function to the extracted value .. so in ap(f,g)(x), f(x) is the extracted function being applied to g(x) which is the extracted value.
since f applied to x returns another function .. well .. that's why f is a binary function
Tom Harding
@i-am-tom
May 20 2017 20:35
It’s probably a better intuition to say Applicative (specifically Apply) is about merging “boxes”, rather than taking something out and putting it into the other
Bijoy Thomas
@bijoythomas
May 20 2017 20:36
ah ok
Tom Harding
@i-am-tom
May 20 2017 20:36
but yeah: ap :: f (a -> b) -> f a -> f b. If our f is ((->) r), we get ap :: ((->) r) (a -> b) -> ((->) r) a -> ((->) r) b, which we can simplify to ap :: (r -> a -> b) -> (r -> a) -> (r -> b)

but lift is the friend here, and its signature is much more useful: lift2 :: Apply f => (a -> b -> c) -> f a -> f b -> f c => lift2 :: (a -> b -> c) -> ((->) r) a -> ((->) r) b -> ((->) r) c, which simplifies to:

lift2 :: (a -> b -> c) -> (r -> a) -> (r -> b) -> r -> c

… which I think clears it up a lot

(That last type signature, I mean - not the wall of monospace letters and symbols, hah)
Bijoy Thomas
@bijoythomas
May 20 2017 21:00
Yes .. that clearly explains my usage of lift(objOf)(product)(identity) .. thanks
Tom Harding
@i-am-tom
May 20 2017 21:01
:)
Denis Stoyanov
@xgrommx
May 20 2017 21:27
:smile:
Bijoy Thomas
@bijoythomas
May 20 2017 21:35
Now to move on to your implementation of filterM @xgrommx :-)
Michael Rosata
@mrosata
May 20 2017 21:37
@bijoythomas you should put some coffee on for that one :smile:
Bijoy Thomas
@bijoythomas
May 20 2017 21:38
oh absolutely @mrosata .. I had to play with it in the REPL for a while before I realized the lift was doing list comprehension
Michael Rosata
@mrosata
May 20 2017 21:41
I spent some time in the repl with it last night w/the js filterM, then today followed along a post where someone else implemented filterM in Haskell. That helped a lot, though I do feel like when I sit down to break apart how the JavaScript version works I'll probably end up spending an equal amount of time figuring it out.
Denis Stoyanov
@xgrommx
May 20 2017 21:43
:smile: