-
Notifications
You must be signed in to change notification settings - Fork 129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Monad.Make() generates non-tail-recursive all
and all_unit
#62
Comments
I tried messing around with it, but it seems hard to get a tail-recursive implementation of |
My code looks like this:
I came up with this version of
I'm not sure if I'm properly taking the various things |
Yeah, this can blow the stack if you have a monad whose bind defers applying its argument, and then you try to do something like evaluate the end result of the monad: (* Monad whose bind defers calling [f] *)
module M' = struct
module T = struct
type 'a t =
| Return : 'a -> 'a t
| Bind : 'a t * ('a -> 'b t) -> 'b t
let return x = Return x
let bind t ~f = Bind (t, f)
let map = `Define_using_bind
end
include T
include Monad.Make (T)
let rec eval : 'a. 'a t -> 'a =
fun (type a) (t : a t) ->
match t with
| Return x -> x
| Bind (t, f) -> eval (f (eval t))
;;
end In this case, the alternative let all_tailrec ts =
let rec loop vs = function
| [] -> vs >>| List.rev
| t :: ts ->
loop (t >>= fun v -> vs >>| fun vs -> v :: vs) ts
in
loop (return []) ts |
I suspect this
|
Gack, I keep misclicking. Sorry for the spurious notifications. |
(Not sure if you're still wanting my opinion on this, but I'd be in favor of making the standard version as safe as possible and assuming if people want to hyper-optimize this, they won't be using the built-in implementation anyway) |
We have a custom logging-ish monad and just ran into an issue on OS X where we ran out of stack space calling
Our_monad.all
on a list with ~100,000 elements.I noticed that
Monad.Make
generates this:https://github.com/janestreet/base/blob/master/src/monad.ml#L59
It's structured in basically the way you'd write a tail-recursive loop, but the
>>=
prevents it from being tail-recursive.It's not entirely clear to me if it's possible to make this tail recursive but it's worth thinking about.
(Our workaround was adding custom
all
andall_unit
functions)The text was updated successfully, but these errors were encountered: