
Hello all, I found some implementations of Monads in javascript, but they all do not allow capturing the intermediate results. My question is: "what is the ultimate cause for this"? In haskell the second argument to (>>=) is a function a->Mb which can be written as a lambda expression, e.g. \x->[x]. In javascript such a function would be written as function(x) {return[x]}. Did I get this right: in haskell the chain of >>= is constructed from the end? So chaining a->Mb and b->Mc gives you a->Mc, which is again suitable as a second argument to (>>=), right? So why can't I do this is javascipt? Or can I? The reason I am asking this is because I am trying to beautify callbacks. An asynchronous ajax call needs a function argument, which will be executed once the call completes. But what if I want to take the results of the first call, do something with them and pass it to a second ajax call, where I would again have to pass another function argument. I would end up with a deeply nested structure of lambdas, something like f(a,b,...function(...){ ... g(... function(...) I had some hopes that chaining functions monad-style would ease my pain. I might be on the wrong track though, feel free to tell me so. -- Martin -- Martin

Martin Drautzburg
I found some implementations of Monads in javascript, but they all do not allow capturing the intermediate results. My question is: "what is the ultimate cause for this"?
In haskell the second argument to (>>=) is a function a->Mb which can be written as a lambda expression, e.g. \x->[x]. In javascript such a function would be written as function(x) {return[x]}.
Did I get this right: in haskell the chain of >>= is constructed from the end?
Composition by (>>=) is by definition associative, so it really doesn't matter how you set your parentheses.
So chaining a->Mb and b->Mc gives you a->Mc, which is again suitable as a second argument to (>>=), right?
Yes, but beware that you may be confusing (>>=) with (>=>).
So why can't I do this is javascipt? Or can I?
I don't see why that should be a problem. Note that there are many different ways to represent monads. Haskell represents them in terms of 'fmap', 'return' and (>>=).
The reason I am asking this is because I am trying to beautify callbacks. An asynchronous ajax call needs a function argument, which will be executed once the call completes. But what if I want to take the results of the first call, do something with them and pass it to a second ajax call, where I would again have to pass another function argument. I would end up with a deeply nested structure of lambdas, something like
f(a,b,...function(...){ ... g(... function(...)
I had some hopes that chaining functions monad-style would ease my pain. I might be on the wrong track though, feel free to tell me so.
You probably are, because the usefulness of monads depends a good deal on syntax. ECMA-based languages like JavaScript, ActionScript, Haxe, etc. have a terrible syntax for anonymous functions. To give you an alternative, this really sounds like you're looking for a continuation-based solution. Continuation passing style could really solve your problem elegantly even in JavaScript. Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/

On Wednesday, 13. July 2011 00:03:44 Ertugrul Soeylemez wrote:
I had some hopes that chaining functions monad-style would ease my pain. I might be on the wrong track though, feel free to tell me so.
You probably are, because the usefulness of monads depends a good deal on syntax. ECMA-based languages like JavaScript, ActionScript, Haxe, etc. have a terrible syntax for anonymous functions.
To give you an alternative, this really sounds like you're looking for a continuation-based solution. Continuation passing style could really solve your problem elegantly even in JavaScript.
Right. It did. It sometimes doens't work to define the callback *after* the function which needs the callback. It is not always easy to find out *when* things need to be defined in javascript. Luckily in Haskell there is no "when". Still in most cases it works and the code looks like regular procedural code, where control flows from top to bottom. And I could nicely write code where the callback makes another callback etc. Thanks. -- Martin

On 23:18 Wed 13 Jul , Martin Drautzburg wrote:
Right. It did.
It sometimes doens't work to define the callback *after* the function which needs the callback. It is not always easy to find out *when* things need to be defined in javascript. Luckily in Haskell there is no "when".
Still in most cases it works and the code looks like regular procedural code, where control flows from top to bottom. And I could nicely write code where the callback makes another callback etc.
Thanks.
Could you give an example how CPS helped your situation? I'm trying to grok continuation passing style, but for now it just seems to complicate and/or slow down code (stack) -- Mats Rauhala MasseR

On 14 Jul 2011, at 09:03, Mats Rauhala wrote:
Could you give an example how CPS helped your situation? I'm trying to grok continuation passing style, but for now it just seems to complicate and/or slow down code (stack)
This obviously isn't Martin's example, but hopefully this should help. In a 3D game engine, the norm (in procedural land at least) is to have calls like someInWorldObject.animate(someAnimation). If you want to run that animation, and then another, the norm is to set a timer to fire when the animation is complete and to call another call like that. My engine by comparison uses CPS – whenever you ask the engine to run an animation of some kind you must specify either a) that it repeats indefinitely, or b) has a continuation to deal with what happens after that animation is complete. The result is that calling code doesn't have random timers floating around, and can define what happens at the completion of an animation in a closure, inline with creating that animation. Apple's CoreAnimation also uses continuation passing style for a similar purpose. Both of these examples use CPS because it allows things to happen asynchronously – an animation can disappear off and run, and then something come back to you once it's finished. I have also found CPS can clean up synchronous code too. Take a look at CPBrainfuck on hackage – I personally think it's one of the cleaner implementations of BF out there, though I will freely admit it's not the fastest. Thanks Tom Davie

Mats Rauhala
I'm trying to grok continuation passing style, but for now it just seems to complicate and/or slow down code (stack)
In general CPS will even improve efficiency, in some cases asymptotically [1,2,3], but that's not their main point. Delimited continuations are the mother of all control constructs, so you can implement many kinds of control flow like concurrency (coroutines), resumable exceptions (or basic exceptions for that matter), forks and reunions, etc. Many Haskell abstractions make use of them; iteratees to name one, on which I rely heavily. Also most of the libraries I upload to Hackage use continuations a lot. For a web application continuations help a lot with some of the difficulties of the stateless HTTP, for example form processing and session management. Along with every link goes a continuation, which is the logical future of the computation. This enables you to write your web application almost totally disregarding the statelessness, like your application would talk to a local user on a terminal. The user session becomes a coroutine of the web server. [1] http://www.iai.uni-bonn.de/~jv/mpc08.pdf [2] http://hackage.haskell.org/package/monad-ran [3] http://comonad.com/reader/2011/free-monads-for-less/ Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 14/07/11 19:01, Ertugrul Soeylemez wrote:
Also most of the libraries I upload to Hackage use continuations a lot. Do you have a few examples?
- -- Tony Morris http://tmorris.net/ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk4etLwACgkQmnpgrYe6r60BfgCeMHNVU+xZfZjqQmmbyFs0Ep0V 0sIAn1ssPQXqeVakyTU3xC2xynuOg9jg =mLjy -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160
Tony Morris
Also most of the libraries I upload to Hackage use continuations a lot.
Do you have a few examples?
The contstuff library is probably the most important example here. It is an advanced monad transformer library with many features not found in other libraries like mtl or monadLib. But it takes some time to get used to the CPS-iness and the slightly different semantics following it. Other examples are ihttp, ismtp and netlines, which use contstuff and the enumerator library, both CPS-heavy libraries. Unlike other libraries I regard the iteratee interface as a feature, not as an implementation detail which should be hidden. And for the sake of completeness the dnscache library is a caching DNS resolver library, which also uses contstuff and provides a StateT interface for those, who don't like IO-global state. Greets, Ertugrul - -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAEBAwAGBQJOHrweAAoJENVqN/rl3Y0RJakQALVeXbTFBFwp3nUbHVfFM4lb y0sp8LMoAh/lXz5dziJ1UScLOVorztz0c1ppmMlITDjp3eSkc4RryqKdovhOJJUt 9oGVY/rQklr/sMZlIOGTQIEU2fl0nmZpP3gkKGV4bSBfPozN8F6r5o2OgRW412rq cHOCTVK+5HxNGtBN46cntV8sByln1xhfAYma3l65FGJlsN9FNBC4vxzJO1nfAHwy 75Ml8XLLD1cqcCr43gP7yJmZ6NZvqKjikzptn8QIxKnXgVqMnL0lKqTKSPMHgZPs iWVLhj2BEXxqNmxL8Xzqf6XCsBtBrJsQupOdUAUkH630iyMB34zoVosRyIbjBF18 S7gF2QcxiqxDpbpzqjSJcMffcsAGeBPVdymEEtd8dJEMuuW1D7+tsRC3gm/aYZJ1 TV+yAxyok+f0jZ08y9yTjiMatSNXzNON/NQz7ORMX7jmi2UvFrlNB9OffA424g9a 392SNxfhfhBKmdh3J91EK8feXozbtvSP2t+0rt/Ie5Lj6OrgCg4kQ5gu7nGYvlJ7 0h01hKBeBtg1J74RKesR+5EP6rSbqifLPSHXmpT5V5zB5C3++5UyVWKYipCFeNmW fP+HrdyzmXiRkPWMSdI9GQisYjKbeFBnLgK77n4FOcpyBoJAPp/8iplEj8J1zb6v K1hYqIelbzwAmy7OrHOf =A9sn -----END PGP SIGNATURE-----

On Thursday, 14. July 2011 10:03:23 Mats Rauhala wrote:
Could you give an example how CPS helped your situation? I'm trying to grok continuation passing style, but for now it just seems to complicate and/or slow down code (stack)
Well it turned out my problem was entirely syntax. If had understood, that an ajax call basically looks like this: // make two successive ajax calls callAsync (remoteFunction1, ["arguments"], function(ret,exc) { //do something with ret and exc var x = ret[1] callAsync(remoteFunction2, [x], function(ret,exc) { // do something else }} You make a remote call and specify what shall happen when the call returns by providing an anonymous callback function. The callAsync itself immediately returns. My only problem was the ugly nesting when I want to place multiple ajax calls which need to be executed in a precise order as in the example above. I cannot simply make the first call and return to make the second call. I would have no idea where exceution would commence after the return. That chain of function calls builds its own little world and you never "return" from this world. This reminded me of haskell Monads which can also create their own little worlds, where e.g. state is passed around . This is why I asked here. But it turned out it had little to do with Monads. Still it is a functional issue. I believe the code above is already CPS, but very ugly. For some reason I hadn't seen, that there is no need to define the callbacks inline, but I might as well assign them to a variables. Then the above code looks like: callAsync (remoteFunction1, ["arguments"], callback1); var callback1 = function(ret,exc) { //do something with ret and exc var x = ret[1] callAsync(remoteFunction2, [x], callback2) } var callback2 = function(ret,exc) { // do something else } This is more gentle to my eyes. The only difficulty is that callback1 and callback2 need to be defined at the time callAsync is called. Usually this is the case. I could of course reverse the order, which would make things safer, but then control will flow bottom- up, whereas all the regular code executes top-down. -- Martin

Back to the question "why can't I get the intermediate results" In Haskell I can do things like f::Int->[Int] f x = [x+1] z :: [Int] z = do y1 <- [1,2,3] y2 <- f y1 return (y1*y2) i.e. I can access an intermediate result y1 and the end of the chain. When I write this without do notation I get z' = [1,2,3] >>= \y1->[y1+1] >>= \y2->return (y1*y2) which of course works just as well. However I must not put parentheses around the lambdas: z' = [1,2,3] >>= (\y1->[y1+1]) >>= (\y2->return (y1*y2)) Not in scope: `y1' However z' = [1,2,3] >>= (\y1->[y1+1] >>= (\y2->return (y1*y2))) works again, which misled me to believe that (>>=) associates to the right. In javascript a lambda would look like this f = function(y1) {return [y1+1]} I cannot see how I could possible write a function (>>=) which chains such lambdas such that I can still access the arguments outside the function bodies. It is like there are always parentheses around the lambdas. Well there actually are braces in javascript, but it can't be just the syntax. So what is javascript missing? Is it because in haskell a lambda is just an expression wheras in javascript it is something special? -- Martin

Martin,
z' = [1,2,3] >>= (\y1->[y1+1] >>= (\y2->return (y1*y2)))
I'm not a Haskell expert, but I think the idea here is that the second lambda is defined *inside* the first one. I think that's the only way that it can access the first lambda's argument. I don't know much Javascript, but here is a small Perl snippet that (kinda) implements the list monad and your example: use strict ; use Data::Dumper ; sub bindM { my $xs = shift ; my $fx2ys = shift ; # maps and concats in one shot my @ys = map {@{$fx2ys->($_)}} @{$xs} ; return \@ys ; } sub returnM { my $x = shift ; return [$x] ; } sub z { my $arg = [1,2,3] ; bindM($arg, sub { my $y1 = shift ; bindM([$y1 + 1], sub { my $y2 = shift ; returnM($y1 * $y2) ; }) ; }) ; } print Dumper(z()), "\n" ; Since $y1 is local to te first lambda, you have to define the second one inside. Patrick
works again, which misled me to believe that (>>=) associates to the right.
In javascript a lambda would look like this
f = function(y1) {return [y1+1]}
I cannot see how I could possible write a function (>>=) which chains such lambdas such that I can still access the arguments outside the function bodies. It is like there are always parentheses around the lambdas. Well there actually are braces in javascript, but it can't be just the syntax.
So what is javascript missing? Is it because in haskell a lambda is just an expression wheras in javascript it is something special?
-- Martin
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- ===================== Patrick LeBoutillier Rosemère, Québec, Canada
participants (6)
-
Ertugrul Soeylemez
-
Martin Drautzburg
-
Mats Rauhala
-
Patrick LeBoutillier
-
Thomas Davie
-
Tony Morris