[MLton-user] Extended Basis Library: iterating thunks

Vesa Karvonen vesa.a.j.k at gmail.com
Tue Apr 17 00:36:45 PDT 2007


On 4/17/07, Geoffrey Alan Washburn <geoffw at cis.upenn.edu> wrote:
[...]
> +   val iterate : 'a t -> Int.t Effect.t
> +   (** {iterate thnk n == (thnk () (* 1 *); ... ; thnk () (* n *))} *)

I don't like the type of this.  A thunk is a delayed computation that you
invoke for the computed value (unit thunk is a sign of a mistake).  The
type of iterate seems error prone to me.  For example, you can easily call
it accidentally with a partially applied function inside an explicit
thunk:

  iterate (fn () => curried a b (* Oops! Forgot the last argument: c. *)) n

I think that when a non-unit return value is always ignored, it should be
explicitly visible at the call site.  For the same reason, I don't
particularly like the type of app and even less the type of appWith in the
MONAD_EX signature, but those are more arguable, because it may be costly
(performance wise) to ignore the result (an extra bind may be required).
In this case, however, the cost is always negligible or zero (function
composition is optimized by all serious ML compilers and in most cases
with MLton the cost of composing with ignore is literally zero).

To me, a more natural function to provide would be either

  val repeat : Unit.t Effect.t -> Int.t Effect.t

or

  val repeat : 'a Effect.t -> Int.t -> 'a Effect.t

(or some permutation of the arguments of either) in the Effect : EFFECT
structure.

Instead of writing

  Thunk.iterate th n

you would write (using the former repeat)

  Effect.repeat (ignore o th) n

or (using the latter repeat)

  Effect.repeat (ignore o th) n ()

-Vesa Karvonen



More information about the MLton-user mailing list