[Haskell-cafe] Clean Dynamics and serializing code to disk
Claus Reinke
claus.reinke at talk21.com
Thu Dec 6 08:36:27 EST 2007
if you want to make something like this for haskell (and
i'd very much like to use it!-), there are several issues,
including:
1 handling code:
- going for a portable intermediate representation,
such as bytecode, is most promising, especially
if the code representation is fairly stable (if you're
worried about performance, choose a representation
that can be compiled further by the backend on
the target machine)
- shipping the code objects, and serializing only
pointers into those, then linking into the objects
dynamically on load, can work if platform and
compiler (ghc versions aren't abi-compatible)
don't change
2 handling types:
- 'out e' needs a runtime representation of the static
type of e;
- 'e <- in' needs to compare e's type representation
at runtime against the static type expected by the
usage context
- types evolve, type representations evolve
- haskell's Dynamic doesn't handle polymorphic
types, and its type representations are not
standardised, so they can change even if
the types do not (there's no guarantee that
reading an expression written by another
program will work)
- doing a proper integration of Dynamic raises
other issues wrt interactions with other type
system features (see the Clean papers for
examples) or wrt parametricity (if any type
can be wrapped in/extracted from a Dynamic,
can you now have type-selective functions of
type 'a->a'?)
3 handlings graphs: in a typical functional language
implementation, there are several parts that need
to do this already, although they tend to be
specialised to their intended use, so they might
not cover all needs for general serialization
- a distributed implementation needs to ship
graphs to other nodes (but often ships code
in a separate setup phase..)
- the memory manager needs to move graphs
between memory areas (but often does not
touch code at all)
graph representations evolve, so if you can reuse
code from one of the existing parts here, that will
save you not only initial time but, more importantly,
avoid a maintenance nightmare.
4 surviving evolution:
if you got all of that working, the more interesting
issues start popping up
- implementations move on, can your code keep up?
- programs move on, can your system handle versions?
- the distinction between static/dynamic has suddenly
become rather blurry, raising lots of interesting
opportunities, but also pointing out limitations of
tools that rely on a fixed single compile-time/
runtime cycle
many of those issues were investigated long ago,
in the area of orthogonally persistent systems
(including types and first-class procedures), see
a thread from earlier this year for a few references:
http://www.haskell.org/pipermail/haskell-cafe/2007-June/027162.html
non-trivial, but doable - you'd probably spend a
lot more time thinking, investigating current code,
prototyping options, and sorting out issues, than
on the final implementation. it is the kind of problem
where you either spend a lot of time preparing an
overnight success, or you start hacking right away
and never get anywhere!-)
claus
ps: i implemented first-class i/o for a pre-haskell
functional language (long gone now) - i experimented
with dynamic linking of object code, but went with
byte code, didn't have to struggle with types, because
the language had runtime types and checking anyway,
and was able to reuse code from the distributed
implementation for storage/retrieval. and saw only
the very early stages of 4;-)
More information about the Haskell-Cafe
mailing list