Jacques Garrigue <garri...@math.nagoya-u.ac.jp> writes: > Hi Goswin, > > Actually I remember discussing this issue with Xavier Leroy a long time ago, > and we ended up concluding that this could be done in a clean way by using > a bit pattern not yet used for ocaml values. > > Our idea was that rather than put some restriction on the shallowness of > types (which is very hard to implement), one should just allow arbitrary > nesting > of option types, and represent the sequence "Some (Some (... ( Some None) > ...))" > as an integer. > I think I even tried an implementation, but we then concluded that there > was not enough demand to put it in the compiler.
The advantage of providing it by the compiler would be to allow pattern matching. > However there is nothing wrong with providing it as a library. > The basic idea is that you have only two kinds of values in ocaml: > integers, which have their lower bit to 1, and pointers, which must > all be multiples of 4 (on 32-bit architectures). > So the pattern (v % 4) == 2 is not used. Actualy isn't (v % 4) == 2 an exception? caml/callback.h: #define Make_exception_result(v) ((v) | 2) #define Is_exception_result(v) (((v) & 3) == 2) #define Extract_exception(v) ((v) & ~3) So returning an Sopt.none in a callback would be taken as exception. :) > Here is the code: > > module Sopt : sig > type +'a t > val none : 'a t > val some : 'a -> 'a t > val is_none : 'a t -> bool > val arg : 'a t -> 'a > val is_sopt : 'a t -> bool > val depth : 'a t -> int > end = struct > type 'a t = int > let null = (Obj.magic (Some 0) land 2) land 1 > let none = null + 1 > let is_none x = x > 0 && x < 1 > let is_sopt x = is_none (x land 1) > let some (x : 'a) : 'a t = > let y : 'a t = Obj.magic x in > if is_sopt y then y+2 else y > let arg (x : 'a t) : 'a = > if is_sopt x then Obj.magic (x-2) else Obj.magic x > let depth x = > if is_sopt x then x lsr 1 else 0 > end WOW. That is some code. Thanks for sharing that. > The code for null tricks the compiler into creating a null pointer. > I avoiding using the simpler (Obj.magic (Some 0) land 0) in case land is > optimized. > By adding 1 to this value, one creates a 2 at the C level. > For ocaml this value is "strictly between" 0 (i.e. 1) and 1 (i.e. 3). > Sopt.some checks whether a value is such an sopt, in which case it adds 2 to > it to > add a Some constructor, otherwise it returns the value itself. > Sopt.arg does just the opposite. > Sopt.is_sopt and Sopt.depth are only exported for demonstrative purposes. > > # Sopt.depth (Sopt.some (Sopt.some (Sopt.some Sopt.none)));; > - : int = 3 > # Sopt.depth (Sopt.some (Sopt.some (Sopt.some 0)));; > - : int = 0 > > Of course this precludes using the above bit pattern for anything else, > but otherwise this should be completely type-safe. > (At the theoretical level at least, I'm not 100% sure of the trickery used > here > to have the compiler work on C level integers) > > Cheers, > > Jacques Garrigue The implementation relies on specific aspect of the compiler to construct those values. I would give it a 99% chance to fail with an llvm backend for ocaml for example. Using C stubs that directly manipulate the bits seems a better approach. For example nothing says x + 2 can't be implemented as value add(value x, value y) { return (x & ~1) + y; } as opposed to value add(value x, value y) { return x + y - 1; } MfG Goswin -- Caml-list mailing list. Subscription management and archives: https://sympa-roc.inria.fr/wws/info/caml-list Beginner's list: http://groups.yahoo.com/group/ocaml_beginners Bug reports: http://caml.inria.fr/bin/caml-bugs