Maybe I should commit it on a branch a link to that commit.

no biggie.

@raine Obviously you can edit the Cookbook wiki page itself. When I cloned your cookbook wiki folder, I got only the two actual wiki pages, so I'm not sure what it is you would like to do.

playing with binary curried compose. comments welcome. https://gist.github.com/buzzdecafe/b00905f6487725173ff7

so, with that you can pass arguments further than to just the first function

yes

i don't really have intuition on how compose should work beyond the simple cases, but there have been some where :point_up: would have been useful

that took a little thinking to wrap my brain around it

a long composition could wind up being very high arity. which may come into conflict with the arbitrary limit of 10 (in

`nAry`

)
which is an argument for taking over handling arity and not using f.length

Won't be in front of a computer for a while, but something is messing with my intuition. That last example looks like it *shouldn't* work.

Looks like you're composing two copies of

`am`

, each of which will need three arguments. But you only supply four, plus maybe one that's passed along.
I'll look when I can play with it better.

anyone know a function that would filter/traverse a deep data structure and return values that satisfy a predicate?

hm, ramda/ramda#473

I remember that one and also I remember discussing the need for the dispatch. I'm quite certain that one of the examples was calling

`filter`

on some tree structure, probably passing `even`

or `odd`

for an example predicate.
But I don't know of an implementation.

Looking at the impl' of R.find, am I right that if Array.prototype.find is implemented, R.find is simply dispatched to Array.prototype.find?

Not right. Array "methods" don't get dispatched

how is that magic done?

does _dispatchable blacklist arrays?

indeed it does

so my forEach proposal should be trivial.

ya @CrossEye, i've updated the gist with a proper example.

`cuz composing artiy 3 with arity 3 = arity 5

you can play with it here: http://bit.ly/1FlofuJ

I'm a bit confused about what this function does.

@joneshf it just composes 2 functions. but then you can feed in all the arguments at once, or partially apply however many you need

so it returns a function of length

`(f.length - 1) + g.length`

i see

how does it work for HOF?

say you have

`foo : (a -> b -> c) -> a -> b -> c`

and `bar : a -> a -> a`

those are pretty bad examples

how about

`foo : (a -> b -> b) -> a -> b -> a -> b`

and `bar : b -> a -> b -> b`

so if you do

`cc(foo, bar)`

what type would that have?
let's see .... should get out a function of arity 6 (4 + 3 - 1). the

`b`

returned from `bar`

must be a function `(a -> b -> b)`

so if

`f = cc(foo, bar)`

then `f :: b -> a -> b -> a -> b -> a -> c`

i think

...

'cuz

`bar(b, a, b)`

returns function `b`

, which is passed on to `foo(b, a, b, a)`

iow

`foo(bar(b, a, b), a, b, a) => c`

?

hmm, so if i wanted

`b -> a -> b -> a -> b`

i would still use `compose(foo, bar)`

?
they are pretty similar. what you can't do with compose is pass all the arguments at once.

you have to know the structure of the composition and subdivide, e.g.

`f(b, a, b)(a, b, a)`

or you could try

`f(b)(a)(b)(a)(b)(a)`

but at present

`R.compose`

does not curry the function it returns.
which to my mind is a big problem

`cc`

guarantees the output function `f`

is curried
i'd rather not have any more

`compose`

functions ... but i find the current one unsatisfactory
oh, i see

so it sounds like i still wouldn't get what i want then?

if i want

`b -> a -> b -> a -> b`

from `foo : (a -> b -> b) -> a -> b -> a -> b`

and `bar : b -> a -> b -> b`

with auto-currying, it looks like I have to wire that together manually
my command of types is not as strong as yours.

maybe it'd help with different variables :)

indeed

so we get a function

`baz = foo . bar`

so

`baz`

has signature ....
as above at present

if i want

`b -> a -> c -> a -> c`

from `foo : (a -> c -> c) -> a -> c -> a -> c`

and `bar : b -> a -> c -> c`

with auto-currying, how do i make this happen?
that is, I want to take the first argument, and apply bar to it, getting back

`a -> c -> c`

then take that and apply

`foo`

to it, getting back `a -> c -> a -> c`

.
light dawns on marblehead

`(b) => foo(bar(b))`

with auto-currying
i think i understand now

:)

that is a different evaluation order, yes?

should be the same

```
λ: let foo = undefined :: (a -> c -> c) -> a -> c -> a -> c
λ: let bar = undefined :: b -> a -> c -> c
λ: :t foo . bar
foo . bar :: b -> a -> c -> a -> c
```

`R.compose`

gives the right type, but it's not auto-curried, as you say
`R.cc`

gives autocurrying but it sounds like the wrong type.
I've long been the holdout on autocurrying the output of various things. I'll probably give in eventually.

But it doesn't play well with certain JS constructs.

@buzzdecafe: Is there a reason you repeat

`R.cc(R.add, R.multiply);`

rather than just use `am`

in the final example?
just to be explicit

ok

should be the same

yes, I had to test just to make sure my intuition wasn't shot. But didn't understand if there was some deep reason for not using the reference that I wasn't seeing.

to get what you are after @joneshf would I have to curry the result of curry?

now we're talking :smiling_imp:

I think you would... if it returns a function.

oh i've no idea.

oh i doubt that

my command of js is not as strong as yours. ;)

you are too kind

The real trouble is where JS starts to interfere with what we really **want** to do... and it seems to be happening a lot lately.

what other interference has there been?

@buzzdecafe ah, you know, I think these are just two different functions.

@joneshf i am on a quest to replace

`useWith`

with a straight compose. but i don't know if i can do it
`useWith :: (a, b -> c) -> (x -> a) -> (y -> b) -> c`

i think
He's never liked my function. Always been the jealous sort, really.

is that right?

haha yep

yes, although technically its variadic, that's the main use-case.

right. i simplified to keep the sig somewhat comprehensible

and

`(x -> a)`

could be (`x,y,z,... -> a)`

etc.
Not really, those are unary.

right, my mistake

The initial function can take as many args as necessary.

they have to be

and therefore there can be many

`(x -> a)`

-style functions.
Actually,

`useWith :: (a, b -> c) -> (x -> a) -> (y -> b) -> (x, y -> c)`

yeah

it'd have to

you know

that syntax always confuses me

Replace the commas with arrows if that helps.

`(a, b -> c)`

reads to me as a 2-tuple with the first part being `a`

and the second part being `b -> c`

They're just not actually curried functions.

`function(a, b) {return c;}`

ah, maybe clearer is

`(a,b) -> c`

we're making this up as we go

well it's certainly more ml-ish

yeah, and we need at some point to find the clearest way to get this across and then take another pass through the docs with a clean syntax.

:sleepy:

so what's wrong with

`useWith`

?
`useWith(f, g, h):: function(x, y) {return f(g(x), h(y));}`

@CrossEye is right, i am just trying to undermine him personally.

haha

It's complex, and no-one else uses anything like it.

If feels as though we're trying to squeeze something into the FP world through a back door.

it is a composition function, and it is clearly useful

seems like we ought to be able to get it out of

`compose`

I still haven't seen anything that does what it does in JS. But it does feel as though there should be.

but haven't figured out how yet

Mike is on a mission to have one

`compose`

to rule them all.
that would be nice

how many composition functions do we have now?

4?

I can't count that high

Fwiw, useWith would have mean much more intuitive if it was named adjustArgyments or something like this

`compose`

, `pipe`

, `composeP`

, `pipeP`

, `useWith`

, `converge`

. Probably others.
i forgot

`pipe`

!
don't we have lens composition as well?

prolly

gtg

`composeL`

?
By the way, I have a patch to replace

`R.curryN`

and `R.nAry`

with `R.curryMinMax`

. I refuse to pay $15/day for hotel Wi-Fi, though, so expect a PR on Monday. :)
hahaha maybe we could all chip in!

ok

I agree that we have too many composition functions. Thanks for investigating solutions, @buzzdecafe!

my pleasure! beats the hell out of closing issues

well it certainly looks like something generalizable.

it actually looks like

`liftN`

with a more general signature
for the

`Function`

instance of `Apply`

more general in the sense that it can take different

`f`

s
so backing up a second ....

`lift2 : Apply f => (a -> b -> c) -> f a -> f b -> f c`

for the sake of argument (no pun intended)

instantiate the

`f ~ (x ->)`

and you get:

`lift2 : (a -> b -> c) -> (x -> a) -> (x -> b) -> x -> c`

but you want:

`useWith2 : (a -> b -> c) -> (x -> a) -> (y -> b) -> x -> y -> c`

we have general

`liftN/lift`

http://ramdajs.com/docs/#lift
yes, your

`lift2`

and `useWith`

sigs are tantalizingly close
oh, i meant this one: https://github.com/ramda/ramda-fantasy/blob/master/src/lift2.js

you naively assume i know what is in libraries with my name on them

:)

Actually, that

`lift2`

is `converge`

yep

1 down!

right

oh!

you need a higher kinded thing to talk about

erm

need to talk about more type variables

like a

`Bifunctor`

or `Profunctor`

.
let's see...

@asaf-romana: No name seems great At one point, we had a two-stage version of `useWith`

that worked like this:

`var project = use(map).with(pickAll, identity)`

But I was the only one who liked that.

I really thought that read better and was more clear. But it's a very strange construct in an FP library.

@joneshf: Is a

`Profunctor`

a `Functor`

that's lost its amateur status?
that does seem very simple

also :)

so `Functor`

s are covariant right?

Given a function from `a`

to `b`

, you can take a `Functor`

`f a`

to a `Functor`

`f b`

aka,

`map : Functor f => (a -> b) -> f a -> f b`

so it's reasonable to think there should be a contravariant

`Functor`

right?
One other thing, folks, note that our

`converge`

is a little more general than the `lift2`

described above, as the secondary functions are variadic, as is the outer function. `lift2`

describes the simplest case.`converge:: (x1 -> x2 -> ... -> z) -> ((a -> b -> ... -> x1), (a -> b -> ... -> x2), ...) -> (a -> b -> ... -> z)`

Here he goes again, trying to make us think!

Given a function from

aka,

`a`

to `b`

, you can take a `Contrafunctor`

`f b`

to a `Contrafunctor`

`f a`

aka,

`comap : Contrafunctor f => (a -> b) -> f b -> f a`

well a

`Profunctor`

is just the combination of those two ideas.
it's contravariant in one argument, and covariant in the other

Given a function from

aka,

`a`

to `b`

and a function from `c`

to `d`

, you can take a `Profunctor`

`p b c`

to a `Profunctor`

`p a d`

.aka,

`promap : Profunctor p => (a -> b) -> (c -> d) -> p b c -> p a d`

i'm following this, but haven't tied it back to

`useWith`

yet
sorry, @joneshf, this will take a while to absorb,

Uh, oh, @buzzdecafe is ahead of me. Gotta quick do some research.

btw @joneshf i am grateful you spend time slumming with us

so my thought is that if you have a profunctor

`p a (p b c)`

you should be able to use some combination of `promap`

and its derivatives to make `useWith`

.
or maybe the type variables are wrong there, i dunno

this benefits me just as much as you

liberating these ideas from the one or two languages that use them mean i'm not relegated to using those languages.

not all are appropriate

and in this case, it's probably not, but it's fun to explore anyway :)

ok so you haven't quite tied it back to

`useWith`

yet either! but you have an intuition that the way is there
oh, btw, functions have a

`Profunctor`

instance
this is where it comes full circle

I can't Google this stuff fast enough!!

so

i.e.

`p a (p b c)`

can be instantiated with `p ~ (->)`

i.e.

`(->) a ((->) b c)`

=> `a -> (b -> c)`

=> `a -> b -> c`

which is the first argument in

`useWith2`

right?

i think so

so you have

`useWith2 : Profunctor p => p a (p b c) -> p x a -> p y b -> p x (p y c)`

although having difficulty parsing

`(->) a ((->) b c)`

oh, sorry

`(->) a b == a -> b`

`(->)`

is a type constructor with two variables.
Damn, that was one thing I *did* know.

it's just written in prefix rather than infix

got it

:)

sorry, i'm still thinking this through in my head as well

so if you have

`f : p a (p b c)`

and `g : p x a`

you should be able to get `lmap g f : p x (p b c)`

then just need the right side

i will have to copy this discussion and study it. i *think* i am following, but as soon as i turn away i'm sure it will all dissolve

yeah, it's a bit of a trip...

I'm hanging on for dear life. Mostly following the sigs. Still no real idea what a profunctor is.

i think this is the key bit:

Given a function from a to b and a function from c to d, you can take a Profunctor p b c to a Profunctor p a d.

oh!

I think i've got it!

is it contagious?

hopefully

:laughing:

infect me, damn it!

```
useWith2 :: (a -> b -> c) -> (x -> a) -> (y -> b) -> x -> y -> c
useWith2 f g h = fmap (lmap h) (lmap g f)
```

oh

where is the emoji for "me with a dumb look on my face"

`lmap : Profunctor p => (a -> b) -> p b c -> p a c`

@CrossEye a profunctor is just a type that is contravariant in its first argument and covariant in its second.

good intuition for profunctors is a function.

and thinking about subtypes also

if you have a hierarchy

`Foo < Bar < Baz`

and a function `quux : Bar -> Bar`

then you can give it a

`Bar`

right?
but you can also give it a

`Foo`

, yes?
ok

following...

what you get back from the function, you can view as being a

`Bar`

yes?
yes

but it could also be viewed as a

`Baz`

how is that guaranteed?

'cuz a

`Baz`

is a `Bar`

?
well since

`Bar < Baz`

`Bar`

does everything that `Baz`

does
a

`Bar`

is a `Baz`

"but 'is a' is close enough among friends"

yeah

ok, i was misreading

`<`

so a

`Profunctor`

just codifies this idea into a explicitness by the programmer
Read

`⊂`

there, if it helps.
yep, i'm with you now

you could say that if you have a profunctor

`p Bar Baz`

that you could convert the two.
erm

wait

ignore that last line

well if the co/contra variance makes sense, that's all there is to

`Profunctor`

s
i think there's a way to relate the idea of subtyping, but i'm not solid on it, so i dont want to muddle around with it

so functions can be profunctors, since they are contravariant in the argument and covariant in the result

you can also think of pipelines and whatnot

if your profunctor

`p Foo Bar`

is a pipeline from `Foo`

s to `Bar`

s, then you can do things to this, like transform some other input to a `Foo`

or change the output from a `Bar`

to something else.
Is there a parallel

`rmap`

to do part of that?
like if you have

`pipeline : p Foo Bar`

and a function `transform : Baz -> Foo`

you can say `lmap transform pipeline : p Baz Bar`

and now you have a pipeline from `Baz`

s to `Bar`

s
yeah

`lmap f = promap f id`

and `rmap f = promap id f`

does that help any with the intuition?

Getting there. .... slowly!

hmm

maybe more examples?

before I do something silly... If I pushed some changes to my mapKeys branch, should I create another PR? It doesn't seem that the PR page is updated to my last commit... but it says that I should just commit further changes to this branch (which is what I did)

maybe it's because I renamed the branch

ugh.

I don't know. The rename might have confused Github. Opening a new PR isn't a big deal, though.

done.

learned my lesson....

Here's an example of a profunctor using a Moore machine as the

`p`

.
mumble mumble.. google "moore machine" mumble mumble

oh

sorry, i thought moore machines were accessible. I jus remember people talking about them like everyone knew what they were.

i never really knew what they were either

simple sort of state machine. just never saw the term before.

yeah

I think you can represent a calculator as a moore machine

or maybe not

i dunno

like i said, not too confident with them

finite state transducer; that makes sense.

but the point is that you can transform the input alphabet to accept a different alphabet

and you can transform the output to produce different output

using the profunctor stuff.

FSMs bring back one of the few CS courses I had in college. But that's nearly 30 years ago...

:)

i absolutely love this gitter room

i'm thinking that the m in mvc can be a profunctor

actually, maybe all three could

Math is more familiar, as I got degrees in that stuff. But my very least favorite course in grad school was Category Theory. Now it turns out the damned stuff might have been useful after all. :frowning:

well most of the stuff we're talking about is a bastardization of real CT

Understood, but it's all related in ways that would probably be obvious if I'd paid more attention way back when.

well my music degree is not helpful at all.

@svozza yes, me too.

This *may* also help towards understanding profunctors: https://www.fpcomplete.com/school/to-infinity-and-beyond/pick-of-the-week/profunctors