The tracing monad is fascinating. What would be a practical application of it? I've been studying monads through Learn You a Haskell for Great Good but haven't been able to put them into context (other than isolating side effects and enforcing order of execution).
let traceMonad = {
return: fn x =
console.log "Return:" x
x
bind: fn x f =
console.log "Binding:" x
f x
}
console.log (do traceMonad
bind w = 1
let x = 2
bind y = 3
bind z = 4
return w + x + y + z
)
The option monad example might be closer. I'm having trouble figuring out how to get the value out of it though
data Option a =
Some a | None
let optionMonad = {
return: fn x =
Some x
bind: fn x f = match x
case (Some a) = f a
case None = None
}
let m = (do optionMonad
bind x = Some 1
let y = 2
bind z = Some 3
return x + y + z
)
match m
case (Some x) = console.log x
shows an error Error: Type error: Native is not Option 'dwk
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!)
...
(* 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 ->
...
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:
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
Comments
The tracing monad is fascinating. What would be a practical application of it? I've been studying monads through Learn You a Haskell for Great Good but haven't been able to put them into context (other than isolating side effects and enforcing order of execution).
https://github.com/pufuwozu/roy/blob/master/test/trace_monad...
That's actually not a Monad :-)
To be a monad, return must be a left and right identity:
By having return do things other than wrapping the value, the monad laws are broken.Similarly, bind cannot have such effects, it would break its associativity.
The option monad example might be closer. I'm having trouble figuring out how to get the value out of it though
shows an error Error: Type error: Native is not Option 'dwkBug in the type system. Fixed. Roy could be cached so you might need to force a refresh.
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:
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: 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-coreDoesn'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:
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: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! :)