From: Alex Baretta <alex@baretta.com>
To: Ocaml <caml-list@inria.fr>
Subject: [Caml-list] Marshalling unknown types
Date: Mon, 26 Jan 2004 09:22:13 +0100 [thread overview]
Message-ID: <4014CE35.3000503@baretta.com> (raw)
I would like Caml breeders and Caml riders to comment on the following
issue: the need to type-safe unmarshalling of datastructures and the way
to achieve it.
The Marshal module appropriately provides polymorphic functions as
> val from_string : string -> 'a (* Offset parameter omitted *)
Such polymorphism is unable to provide static type safety. I would be
happy with runtime type safety: in other words, I'd be happy with an
exception being thrown at runtime if a datastructure is unmarshalled to
the wrong runtime type. The obvious way to do this is the following.
module Type_safe_marshal = struct
let to_string (ex:exn) = Marshal.to_string ex []
let from_string s = raise (Marshal.from_string s 0)
end
module Foobar_marshal = struct
open Type_safe_marshal
type foobar = Foo of int | Bar of string
exception Foobar of foobar
let to_string (x:foobar) = to_string (Foobar x)
let from_string s = try raise (from_string s) with
| Foobar x -> x
end
open Foobar_marshal
let foo1 = foo 1
let what = from_string (to_string foo1)
Obviously this does not work. For some reason, as someone already
pointed out, pattern matching does not work on unmarshalled exceptions.
When the above code is sent to the toplevel interpreter I get the
following output.
module Type_safe_marshal :
sig val to_string : exn -> string val from_string : string -> 'a end
module Foobar_marshal :
sig
type foobar = Foo of int | Bar of string
exception Foobar of foobar
val to_string : foobar -> string
val from_string : string -> foobar
end
val foo1 : Foobar_marshal.foobar = Foo 1
Exception: Foobar_marshal.Foobar _.
I'm sure that there are excellent reasons why this should occur. So, I
tried a less obvious means of achieving runtime type safety for
unmarshalled objects.
module Type_safe_marshal_2 = struct
let to_string (f:unit -> 'a) = Marshal.to_string f [Marshal.Closures]
(* f is a function which builds and throws an appropriate exception *)
let from_string s () = Marshal.from_string s 0 ()
end
module Foobar_marshal_2 = struct
open Type_safe_marshal_2
type foobar = Foo of int | Bar of string
exception Foobar of foobar
let raise_foobar x () = raise (Foobar x)
let to_string x = to_string (raise_foobar x)
let from_string s = try from_string s () with
| Foobar x -> x
end
open Foobar_marshal_2
let foo1 = Foo 1
let what = from_string (to_string foo1)
let _ = Printf.eprintf "Hey, I managed to build \"what\" alright!\n"
Here I try to build and raise the exceptions at unmarshalling time by
actually marshalling closures of functions know how to throw an
exception containing the datastructure I wish to marshal. However, this
code cannot be run in the toplevel. This is what it says:
Exception: Invalid_argument "output_value: abstract value".
Apparently, closures built by the toplevel compiler cannot be
marshalled. So let's try with ocamlc. I placed the above code in
marshal_foobar.ml and compiled it with ocamlc.
$ ocamlc foobar_marshal.ml -o foobar_marshal
$ ./foobar_marshal
Fatal error: exception Foobar_marshal.Foobar_marshal_2.Foobar(1)
I can find no reasonable explanation for this behavior. I realize that
exceptions are nasty beasts and that the marshalling functions were not
meant for them, but in this case, the exception is only built and raised
*after* unmarshalling occurs, so I don't see why pattern matching should
fail.
***
All this said, O great Camlers, what is your verdict? If my approach is
sound, how can I fix my code to make it work? If my approach is
misguided, how should type-safe unmarshalling be achieved?
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
next reply other threads:[~2004-01-26 8:22 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-01-26 8:22 Alex Baretta [this message]
2004-01-26 10:19 ` Richard Jones
2004-01-26 10:55 ` James Leifer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4014CE35.3000503@baretta.com \
--to=alex@baretta.com \
--cc=caml-list@inria.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox