"variables won't, constants aren't" (sorry, don't remember the source)
The argv-problem and its proposed solutions:
1. fetch argv via the IO monad wherever it is needed
+ it works
- don't want to program everything in monadic style
2. fetch argv via the IO monad once and pass it around explicitly
+ it works
- don't want to pass all these parameters around everywhere
- could just as well use a monad for this -> see 1.
3. make argv a global constant
+ may work (for this problem)
- needs some ad hoc changes to the language and implementation
: hmmm, really global, really constant?
Just a thought - wouldn't first class modules help here?
Not that they were available right now, but let me explain the
idea anyway:
a) you have a collection of declarations and some of them
need access to what seem to be constants *for these
declarations in question*, which is a *local* property.
b) these `constants' are not really constant - argv contains
the *parameters* to the executable. The correct alternative
would be an additional parameter to main, but that's what
the IO monad is for, isn't it?
So we seem to need a way to *parameterize a collection of declarations*
with a *runtime* value. This is why simple parameterized modules would
not help and, if I see this correctly, why even a separate module
language ala SML extended with higher-order functors would not be
enough here - they explicitly address modules *before* runtime.
But with true first class modules, we could do something like this:
MyCompiler argv =
struct
parse = ..... argv ...,
typeIt = .. f optimize inline,
...
f opt inl = ... argv ...,
...
compile = parse >> typeIt >> ...
end
main = getArgv >>= \argv->
checkArgvForErrors argv >>
(MyCompiler argv).compile
Not very realistic, not even Haskell (yet), but I hope you get the
idea. It will not solve your problem immediately, but it may be the
generalization you've been looking for. It avoids passing parameters
as global constants and does not bypass the IO monad when doing
the system interactions this thing was designed for. It is modular,
does not break down for the other problem variants mentioned and
it does not need no ad-hoc restrictions to work.
Of course, if your MyCompiler had only one entry function, a local
definition instead of the local module would do:
MyCompiler argv =
let
parse =
type =
...
in parse >> type >> ..
So first class modules seem to be a natural and useful extension, in
line with usual functional programming techniques. As mentioned in
the other thread, static type inference seems to cost you here: it
converts the simple idea into quite a complex problem. I have also
ignored the issue of (local) type declarations here.
For what its worth,
--
Claus Reinke University of Kiel
email: [EMAIL PROTECTED] Department of Computer Science
http://www.informatik.uni-kiel.de/~cr/ Preusserstr. 1-9, 24105 Kiel