These are chat archives for ramda/ramda

27th
Oct 2016
Nate Abele
@nateabele
Oct 27 2016 01:17
This seems like the most relevant thing: ramda/ramda#1809
Scott Sauyet
@CrossEye
Oct 27 2016 12:07
@JAForbes: mapping over a Map/WeakMap looks reasonable to me. Mapping over a Set scares me a bit. In some very real, if hard to formalize, manner, an important part of map is that it retains the shape of the functor. But what would be the result of mapping square over the five-element set {-2, -1, 0, 1, 2}?
Keith Alexander
@kwijibo
Oct 27 2016 12:51
@CrossEye can you explain a bit more? I'd have thought {4, 1, 0} would be a reasonable result?
(is it that there are fewer items in the resulting Set?)
Andrea Scartabelli
@ascartabelli
Oct 27 2016 13:28

@CrossEye Oddly enough in Scala you get a set of three elements:

val foo = Set[Double](-2, -1, 0, 1, 2)
foo.map(Math.pow(_, 2)) // => Set(0.0, 1.0, 4.0)

Surprised me, but now I'm curious to check with my Scala guys and hear about that

Julien Goux
@jgoux
Oct 27 2016 13:49
Hello
Michael D. Stemle, Jr.
@manchicken
Oct 27 2016 13:49
Greetings and salutations.
Julien Goux
@jgoux
Oct 27 2016 13:49
I want to get the most frequent value in a list, I'm pretty close but I'm missing the last bit :D
Michael D. Stemle, Jr.
@manchicken
Oct 27 2016 13:50
What are you trying?
Julien Goux
@jgoux
Oct 27 2016 13:50
R.pipe(
R.countBy(R.identity),
R.toPairs,
R.reduce(R.maxBy(R.last), 0)
)
it's good until the last function
It returns 0
:/
Michael D. Stemle, Jr.
@manchicken
Oct 27 2016 13:51
What's your input?
Julien Goux
@jgoux
Oct 27 2016 13:53
I have this one for example :

[ [ 'foo', 1 ],                                                                    
  [ 'bar', 1 ],                                                                   
  [ 'baz', 2 ] ]
outputed if I stop at R.toPairs
I just follow the example here : http://ramdajs.com/docs/#maxBy
seems right to me to use R.maxBy(R.last) for a list of pairs
then I should use R.head to get the initial value
oh :o :o :o
R.reduce(R.maxBy(R.last), ['', 0])
worked !
I was comparing 0 to a pair
xD
Michael D. Stemle, Jr.
@manchicken
Oct 27 2016 13:58
There ya go.
You're faster than me.
Julien Goux
@jgoux
Oct 27 2016 13:58
well no, I was comparing the count in the pair with R.last(0) :D
Thanks anyway @manchicken ^^
Nate Abele
@nateabele
Oct 27 2016 13:59
@CrossEye Looks like Haskell has the same behavior: https://downloads.haskell.org/~ghc/6.4.1/docs/html/libraries/base/Data-Set.html
"It's worth noting that the size of the result may be smaller if, for some (x,y), x /= y && f x == f y"
Andrea Scartabelli
@ascartabelli
Oct 27 2016 14:00
out of curiosity Immutable's Set does the same: it has a map method and returns a smaller Set
Nate Abele
@nateabele
Oct 27 2016 14:01
So, proof by prior art? :-)
Andrea Scartabelli
@ascartabelli
Oct 27 2016 14:13
@nateabele Well, as one of my "Scala guys" just reminded me, strictly speaking "as long as the functor returns a Set of values, and as long as the arrow is pure, then the functor is not breaking any rules"
Nate Abele
@nateabele
Oct 27 2016 14:13
That's kinda what I was thinking.
Length isn't strictly part of the 'shape'.
Andrea Scartabelli
@ascartabelli
Oct 27 2016 14:14
He also made me notice that in Scala Set and Lists aren't functors and that he thinks that "the scalaz representation of a functor is more natural, because it represents functors as type classes"
I'm quoting because it's out of my territory, actually
Tomáš Konrády
@tommmyy
Oct 27 2016 14:15
Hello, how to make function in Ramda that do equivalent operation:
(fn, [x, y, ...]) => fn(x)(y)...
Nate Abele
@nateabele
Oct 27 2016 14:16
Hmmm, converge() with call(), I guess?
Tomáš Konrády
@tommmyy
Oct 27 2016 14:17
Cool, a thought about simple reduce
I*
Nate Abele
@nateabele
Oct 27 2016 14:17
Wait... I misread that. Yeah, reduce would work.
Tomáš Konrády
@tommmyy
Oct 27 2016 14:18
@nateabele thank you :)
Andrea Scartabelli
@ascartabelli
Oct 27 2016 14:21
@nateabele Exactly, length or ordering or else aren't part of the shape
I would have considered the length to be part of the shape to tell the truth, but now I'm reconsidering
Tomáš Konrády
@tommmyy
Oct 27 2016 14:25
@nateabele it turned out to be pretty simple:
const reduceCallable = R.reduce((acc, next) => acc(next));
Nate Abele
@nateabele
Oct 27 2016 14:26
Cool.
Keith Alexander
@kwijibo
Oct 27 2016 14:43
@ascartabelli I see it as, Arrays have length, and Sets have uniqueness, as their defining "container" semantics
I did wonder about ordering of Sets though
Nate Abele
@nateabele
Oct 27 2016 14:44
Yeah, I thought sets were ordered.
so I suppose you map over the contents in insertion order, and don't allow any duplicates to be inserted in the return Set (as opposed to removing the existing item and inserting the duplicate)
Barry G
@bgits
Oct 27 2016 14:49
What are the downsides of memoizing a composition other than additional memory allocation? ie: compose(pluck('value'), memoize)
Keith Alexander
@kwijibo
Oct 27 2016 14:49
What about other shapes? If you map over a tree, does the return tree have to have the same number of nodes? a graph?
Keith Alexander
@kwijibo
Oct 27 2016 14:55
@bgvianyc I don't think that does what you intend
compose(g, f)(x) == g(f(x))
Barry G
@bgits
Oct 27 2016 14:57
@kwijibo does it need to be memoize(compose(map(crazystuff), pluck('value')) ?
Keith Alexander
@kwijibo
Oct 27 2016 14:57
so
compose(pluck('value'), memoize) is pluck('value')(memoize(x))
(ie, memoizing your value, not your function)
Barry G
@bgits
Oct 27 2016 14:58
got it, so my question actually applies to the second example I gave.
Keith Alexander
@kwijibo
Oct 27 2016 14:58
@bgvianyc yes; memoize is a decorator
Barry G
@bgits
Oct 27 2016 14:58
How does when decide when it makes sense to decorate with memoize?
Ryan Zeigler
@rzeigler
Oct 27 2016 15:01
when the size of the input set is small and computing the results is slow.
Keith Alexander
@kwijibo
Oct 27 2016 15:02
@bgvianyc I think like you said, memory concerns can guide you here. Think about what your function is doing;
are the results permanently cacheable?
will the function be called with the same arguments a lot?
will the results be more expensive to compute than to cache?
My feeling is that relatively few functions will be worth caching in typical browser-side javascript
Ryan Zeigler
@rzeigler
Oct 27 2016 15:03
you can also 'temporarily' memoize by having an unmemoized version and then memoizing as a utility inside another function if you know that function will repeat the same work a lot (dynamic programming algorithms)
so each time your algorithm runs it gets a fresh memoized version
this can partially ameliorate memory usage concerns
Barry G
@bgits
Oct 27 2016 15:04
This is good food for thought.
Keith Alexander
@kwijibo
Oct 27 2016 15:06
I'm no perf expert, but I'd probably start from a position of looking at some performance profiling to decide what, if anything, to memoize
Barry G
@bgits
Oct 27 2016 15:06
right
Keith Alexander
@kwijibo
Oct 27 2016 15:06
rather than memoize functions as I write them
It's an interesting idea though; what if the default was for functions to be memoized, and you had specifically unmemoize the impure ones?
fenduru
@fenduru
Oct 27 2016 15:29
@JAForbes wow, thanks for the help (pointing out that chain(g, f) === converge(f, [g, identity]))! I should probably go and learn about all of the properties of functions and how they relate to these concepts, because this is the 2nd time I've gotten tripped up by treating functions as values
Keith Alexander
@kwijibo
Oct 27 2016 15:44
@fenduru are you sure chain(g, f) === converge(f, [g, identity]) ? https://goo.gl/WT1KyM
Andrea Scartabelli
@ascartabelli
Oct 27 2016 15:57
@kwijibo
I mentioned ordering only as an example of a property that doesn't define the "shape". Sets aren't ordered by nature, and the docs you mention talks about insertion order in the same way that we could do about object keys.
Regarding trees: it depends, obviously. If some kind of tree has some rule about not having duplicate leafs we may end up in the same "conundrum".
Denis Stoyanov
@xgrommx
Oct 27 2016 16:04
@ram-bot
R.chain(R.add, R.add(10))(10)
ram-bot
@ram-bot
Oct 27 2016 16:04
monad.call(...).apply is not a function
Denis Stoyanov
@xgrommx
Oct 27 2016 16:04
@ram-bot
const chain_ = R.curry((k, f) => r => k(f(r))(r));
chain_(R.add, R.add(10))(10)
ram-bot
@ram-bot
Oct 27 2016 16:04
30
Denis Stoyanov
@xgrommx
Oct 27 2016 16:05
ramda has wrong monadic bind
Travis LaDuke
@laduke
Oct 27 2016 16:57
Can I change key names in an object easily? {foo: 1, bar: 2} -> {x: 1, y: 2}
Brad Compton (he/him)
@Bradcomp
Oct 27 2016 17:00
Beat me to it :)
Travis LaDuke
@laduke
Oct 27 2016 17:01
:thumbsup:
Paul
@pauloliver
Oct 27 2016 17:06
:laughing:
fenduru
@fenduru
Oct 27 2016 18:11
@kwijibo your example is backwards
you did chain(f, g) not chain(g, f)
Denis Stoyanov
@xgrommx
Oct 27 2016 18:13
I did right version. Ramda has bug with monadic bind for function
@ram-bot
R.chain(R.add(10), R.range(0, 10))
ram-bot
@ram-bot
Oct 27 2016 18:17
[ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]
Michael Hurley
@buzzdecafe
Oct 27 2016 19:29
@xgrommx yup. See ramda/ramda/pull/1937
Nate Abele
@nateabele
Oct 27 2016 19:33
You guys have some... interesting... conventions for approving pull requests.
Denis Stoyanov
@xgrommx
Oct 27 2016 19:36
left and right side =)
// ($)    ::                      (a -> b) ->   a ->   b
// (<$>)  :: Functor     f  =>    (a -> b) -> f a -> f b
// (<*>)  :: Applicative f  =>  f (a -> b) -> f a -> f b
// (=<<)  :: Monad       m  =>  (a -> m b) -> m a -> m b
// (<$)   :: Functor     f  =>  a -> f b -> f a 
// (<*)   :: Applicative f  =>  f a -> f b -> f a

// (&)    ::                      a ->   (a -> b) ->   b  -- Data.Function
// (<&>)  :: Functor     f  =>  f a ->   (a -> b) -> f b  -- Control.Lens.Operators
// (<**>) :: Applicative f  =>  f a -> f (a -> b) -> f b  -- Control.Applicative
// (>>=)  :: Monad       m  =>  m a -> (a -> m b) -> m b
// ($>)   :: Functor     f  =>  f a -> b -> f b
// (*>)   :: Applicative f  =>  f a -> f b -> f b

// (.) :: (b -> c) -> (a -> b) -> a -> c
// (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c

// (>>>) :: Category cat => cat a b -> cat b c -> cat a c
// (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
Scott Sauyet
@CrossEye
Oct 27 2016 19:36
@nateabele: how so? (beyond the fact that this is a part-time, and sometimes low-priority commitment from everyone)
Nate Abele
@nateabele
Oct 27 2016 19:36
:camel: and :herb:
;-)
Scott Sauyet
@CrossEye
Oct 27 2016 19:38
Ah yes. The core committers each have themselves an icon. No idea why. But it's more fun than +1.
Nate Abele
@nateabele
Oct 27 2016 19:38
Well I'll grant you that.
Scott Sauyet
@CrossEye
Oct 27 2016 19:46
Sorry to drop my comment earlier and disappear. I don't get much time here lately. Those extra Ord constraints in the Haskell version seem to make this something other than a Functor map. But I may just be confused. It still feels strange, even if others are doing it.
Nate Abele
@nateabele
Oct 27 2016 19:47
Well, my first thought was to write a separate library that just patches all the core prototypes.
Anyway, your call. I'm happy to work up a patch next week, but I may need some help making it transducer-y.
Scott Christopher
@scott-christopher
Oct 27 2016 20:55

Those extra Ord constraints in the Haskell version seem to make this something other than a Functor map

Right, due to the Ord constraint on Data.Set the mapping function is restricted to returning another Ord instance, so it's more of a endofunctor of a something like an OrderedHask category, rather than Hask itself.

But as long as identity and associativity laws hold, then it should be fine to treat as a functor (just restricted to Ord)

> import Data.Set
> let f = (* 42)
> let g = (** 2)
> let xs = fromList [-2, -1, 0, 1, 2]
> (Data.Set.map g) . (Data.Set.map f) $ xs
fromList [0.0,1764.0,7056.0]
> Data.Set.map (g . f) xs
fromList [0.0,1764.0,7056.0]
> :t Data.Set.map
Data.Set.map :: Ord b => (a -> b) -> Set a -> Set b