Giter Site home page Giter Site logo

Comments (30)

buzzdecafe avatar buzzdecafe commented on July 17, 2024 3

They're all specific cases of a more general Semigroupoid idea.

I recall you and @scott-christopher discussing that in the gitter room. i may take a whack at unifying our many composers into one.

Which raises the thought: A good name for a javascript composition lib would be Bach.js

from sanctuary.

benperez avatar benperez commented on July 17, 2024 1

Oh, duh. 🐐

The only limitation I see here is that this form of do notation only really allows you to feed through a single monadic value. You lose the ability to bind different variables to different monadic values in the same do expression like the following example:

foo :: Maybe String  
foo = do  
    x <- Just 3  
    y <- Just "!"  
    Just (show x ++ y)

from sanctuary.

buzzdecafe avatar buzzdecafe commented on July 17, 2024

wow, that is nice sugar. FWIW, I think $do is fine

from sanctuary.

davidchambers avatar davidchambers commented on July 17, 2024

wow, that is nice sugar.

I think so too! Shall I open this for discussion on the Ramda issue tracker? The function could be defined there instead. :)

from sanctuary.

buzzdecafe avatar buzzdecafe commented on July 17, 2024

your call. looks pretty interesting to me.

Can't you also do this:

// $do :: Monad m => [(a -> m b), (b -> m c), ..., (y -> m z)] -> m a -> m z
const $do = R.apply(R.pipe, R.map(R.chain));

?

It also seems like there is a way to write this with ap, but don't have time to prove that right now

from sanctuary.

davidchambers avatar davidchambers commented on July 17, 2024

The types don't line up in your definition, @buzzdecafe. You're fully applying (ahem) R.apply (which takes two arguments).

from sanctuary.

benperez avatar benperez commented on July 17, 2024

Why isn't do a valid identifier?

from sanctuary.

davidchambers avatar davidchambers commented on July 17, 2024

do is a keyword: do...while.

from sanctuary.

buzzdecafe avatar buzzdecafe commented on July 17, 2024

yep, i was reading apply like compose for some reason

from sanctuary.

davidchambers avatar davidchambers commented on July 17, 2024

The only limitation I see here is that this form of do notation only really allows you to feed through a single monadic value.

True. R.compose and R.pipe share this limitation, of course.

from sanctuary.

benperez avatar benperez commented on July 17, 2024

R.compose and R.pipe share this limitation, of course.

I don't really see how that relates. I think you might be able to come up with a way to bind different variables but I'm guessing it would be pretty hacky.

I think this is cool for the single pipeline case though!

from sanctuary.

buzzdecafe avatar buzzdecafe commented on July 17, 2024

I think you might be able to come up with a way to bind different variables but I'm guessing it would be pretty hacky.

indeed. I was trying to come up with some way to do that, but all i could come up with could only generously be called "hacky"

from sanctuary.

joneshf avatar joneshf commented on July 17, 2024

Does do go by other names?

The name you're looking for is Kleisli: https://en.wikipedia.org/wiki/Kleisli_category

What you've Greenspun'd is exactly Kleisli composition. :)

See also: >=> and <=<

from sanctuary.

davidchambers avatar davidchambers commented on July 17, 2024

The name you're looking for is Kleisli

It sounds as though Ramda needs more composition functions. R.composeK and R.pipeK, anyone?

from sanctuary.

buzzdecafe avatar buzzdecafe commented on July 17, 2024

😱

from sanctuary.

joneshf avatar joneshf commented on July 17, 2024

Sorry, I didn't actually look close enough. $do isn't entirely kleisli composition. If you have:

// kleisli : Chain m =>  [a -> m b, b -> m c, ..., y -> m z] -> a -> m z

Then yes.

Also, note that you don't actually need the full power of Monad for this.

from sanctuary.

joneshf avatar joneshf commented on July 17, 2024

It sounds as though Ramda needs more composition functions. R.composeK and R.pipeK, anyone?

No, it definitely needs less (ideally one). They're all specific cases of a more general Semigroupoid idea.

from sanctuary.

davidchambers avatar davidchambers commented on July 17, 2024

@joneshf, do you think such a function should return a -> m z rather than m a -> m z?

I'm having a bit of trouble seeing how something of the shape

R.pipe(
  S.Just,
  R.chain(f),
  R.chain(g),
  R.chain(h),
  R.chain(i),
  R.chain(j)
);

can be rewritten as a pipeline where every function in the pipeline is a partially applied R.chain.

from sanctuary.

joneshf avatar joneshf commented on July 17, 2024

@joneshf, do you think such a function should return a -> m z rather than m a -> m z?

I was just nitpicking, and looking more closely at the haskell stuff.

They're equivalent, so either way is fine, since (f >=> g) x = f x >>= g and x >>= f = (id >=> f) x. So choose either one and you can provide the other easily.

I'm having a bit of trouble seeing how something of the shape
...
can be rewritten as a pipeline where every function in the pipeline is a partially applied R.chain.

Hmm, I think I'm having a brain fart here, or I'm not understanding the question.

from sanctuary.

davidchambers avatar davidchambers commented on July 17, 2024

They're equivalent, so […] choose either one and you can provide the other easily.

That makes sense. :)

I think I'm having a brain fart here, or I'm not understanding the question.

I didn't see at the time how to return a -> m z rather than m a -> m z. I do now. The implementation is a bit more involved, since one must apply R.chain to all the arguments but the first:

// $do :: Chain m => [(a -> m b), (b -> m c), ..., (y -> m z)] -> a -> m z
const $do = R.pipe(R.converge(R.prepend,
                              R.head,
                              R.pipe(R.tail, R.map(R.chain))),
                   R.apply(R.pipe));

[Ramda's various composition functions and the proposed Kleisli composition functions are] all specific cases of a more general Semigroupoid idea.

I'm intrigued by the possibility of a composition function which can perform Kleisli composition as well as "regular" function composition. I've no idea how this is possible. :)

from sanctuary.

joneshf avatar joneshf commented on July 17, 2024

Thinking about it now, I think the only way to make it happen is to wrap the monadic function in a Kleisli type.

from sanctuary.

joneshf avatar joneshf commented on July 17, 2024

Also, if it wasn't clear from the signature Kleisli == ReaderT, and a -> b == ReaderT Identity a b. So that's why I feel these can be unified. But I think without a compiler implicitly passing around things and wrapping/unwrapping, it'd end up being a less than optimal api.

from sanctuary.

CrossEye avatar CrossEye commented on July 17, 2024

But I think without a compiler implicitly passing around things and wrapping/unwrapping, it'd end up being a less than optimal api.

That's often where the rubber meets the road with JS libs. There a lot of 'almost's and 'if only's floating around, usually having to do with its type system.

from sanctuary.

joneshf avatar joneshf commented on July 17, 2024

Thinking about it more, you'd run into the same api issues in haskell. And the ways around it are just as suboptimal, but for different reasons. I guess I just want too much.

from sanctuary.

davidchambers avatar davidchambers commented on July 17, 2024

ramda/ramda#1212 added a variadic version of the proposed $do function as R.pipeK.

from sanctuary.

gabejohnson avatar gabejohnson commented on July 17, 2024

@davidchambers, any interest in revisiting this now that Sanctuary is no longer dependent on Ramda?

from sanctuary.

davidchambers avatar davidchambers commented on July 17, 2024

Absolutely! Let's open a new issue: pipeK is more limited than Haskell's do notation because it doesn't provide access to the results of all previous computations. Would you mind opening an issue for pipeK, @gabejohnson?

from sanctuary.

gabejohnson avatar gabejohnson commented on July 17, 2024

I can do that.

I've also been looking at arrows and categories. Seems like something that would be useful to add to the spec.

from sanctuary.

gabejohnson avatar gabejohnson commented on July 17, 2024

Looks like there's already an issue for it fantasyland/fantasy-land#208

from sanctuary.

gabejohnson avatar gabejohnson commented on July 17, 2024

See #380

from sanctuary.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.