[MLton] Structures inside a function?
Stephen Weeks
MLton@mlton.org
Fri, 21 Jan 2005 07:34:10 -0800
> Hi! I recently ran into a problem where I needed to use a structure
> inside a function. However, this doesn't appear to be possible; what
> do I do instead?
...
> Normally, when you use a residue ring, it is a top-level construction.
> Therefore, I haven't needed this before. However, I was implementing
> Pollard's rho algorithm and then I suddenly needed a ring which was
> parameterized by a function parameter!
>
> I have run into this in several other places, but have always avoided
> the problem. Here, I don't see any choice other than to redefine all the
> methods I need from Math (lots) in local scope, which really sucks.
A trick I sometimes use when I'm this situation and don't want to
refactor in the other way's y'all have discussed is to use a ref cell
to delay instantiation of part of the structure. In your case, the
lone value to be delayed is modulus, but in general, any number of
values could be delayed. Once enough values are delayed, one can lift
the functor applications to the top level, leaving just the value part
inside the function. For your code, this looks like
----------------------------------------------------------------------
signature RESIDUE_PARAM =
sig
structure Base: EUCLIDEAN_DOMAIN
val modulus: Base.t ref
end
functor Residue (P: RESIDUE_PARAM): RING = ...
functor Math (R: RING) = ...
functor Factor (E : EUCLIDEAN_DOMAIN) =
struct
local
structure Base = E
val modulus = ref Base.zero (* dummy value *)
structure R = Residue (structure Base = Base
val modulus = modulus)
structure M = Math (R)
in
fun factor x =
let
val () = modulus := x
open M
in
(* use various methods defined in Math to factor x *)
end
end
end
----------------------------------------------------------------------
For the common case of Residue where the delaying isn't needed, you
can create a wrapper that hides the ref cell.