Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Know what would be awesome? If you could use the monad syntax to clean up async, cb-passing code. I've been learning a lot of Haskell lately too, and I like to think of the monads as returning a set of instructions with side effects to be executed in order. I think this example is kind of trivial. I'd love to see one that does something more than simple addition (IO!)


Jane Street's Async library for OCaml does this: http://ocaml.janestreet.com/?q=node/100. It's excellent, and I now miss it in every other language I use.

Code looks something like this:

    ...
    (* long_running_call : unit -> string Deferred.t *)
    long_running_call ()
    >>= fun result ->
    print_endline result
    ...
Running calls in parallel is easy. Say we want to run a couple of queries against a db at once, and only perform an action once both return:

    ...
    (* Db.query : Db -> Db.Query -> Db.Result Deferred.t *)
    let d1 = Db.query db query1 in
    let d2 = Db.query db query2 in
    d1 >>= fun r1 ->
    d2 >>= fun r2 ->
    ...
If you have questions about getting it set up/using it, the mailing list is the place to ask: https://groups.google.com/forum/#!forum/ocaml-core


Doesn't this have the same problem that Python's Twisted does -- that async calls may lack handlers for error conditions, and so errors may be silently ignored?


Async includes a module called Monitor that lets you correctly handle exceptions in async code. The signature of one of the most commonly used methods is this:

    Monitor.try_with : ?name : string
                       -> (unit -> 'a Deferred.t)
                       -> ('a, exn) Result.t Deferred.t
It takes two arguments. Name is used to tell you what monitor the error was caught by. The second is a function that returns some kind of Deferred.t. The whole thing returns a (deferred) Result.t (: [`Ok of 'a | `Error of exn]), letting you either do something with the results of the async call or handle the error. Usage might be something like this:

    (* query_or_print : Db.t -> Db.Query.t -> Db.Result.t option Deferred.t *)
    let query_or_print db query =
      Monitor.try_with (fun () -> Db.query db query)
      >>| function
      | `Ok result -> Some result
      | `Error e -> print_endline (Exn.to_string e); None


Actually, there are already monadic interfaces for Javascript async code with widespread use. Promises!

http://dojotoolkit.org/reference-guide/dojo/Deferred.html http://api.jquery.com/category/deferred-object/

new deferred objects can be created manually or obtained from say, an AJAX function (this is the equivalent of "return")

async operations can be chained with the deferred.then method (this is a hybrid of "fmap" and ">>=", aka "bind")


Well, there is a Cont monad in Haskell (Control.Monad.Cont). I am not too familiar with it though I know there is a good chapter about it in the Haskell Wikibook (http://en.wikibooks.org/wiki/Haskell/Continuation_passing_st...).


Author here, that's the plan! :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: