I would like create a polymorphic function that converts 8,16,32 bit words into 64 bit word. How can I do it?
UPDATE1
In the basis library all word structures have functions toLarge
and fromLarge
to convert to/from the LargeWord
, which is as far as I understand just a synonym for Word32.
UPDATE2
According to the spec, word size must be power of two, but in SML/NJ I have
Standard ML of New Jersey v110.84 [built: Mon Dec 03 10:23:14 2018]
- Word.wordSize;
val it = 31 : int
- Word32.wordSize;
val it = 32 : int
- Word.toLarge;
val it = fn : word -> Word32.word
> LargeWord.wordSize;
val it = 32 : int
while in PolyML
Poly/ML 5.7.1 Release
> Word.wordSize;
val it = 63: int
> Word64.wordSize;
val it = 64: int
> Word.toLarge;
val it = fn: word -> ?.word
> LargeWord.wordSize;
val it = 64: int
How is that? Why Word.wordSize
is not power of two? And why Word
representation differs in these SML implementations?
UPDATE3
Actually, I want to be able "promote" smaller words into the larger ones using (<<) operator, but cannot figure it out how to do it.
UPDATE4
It seems that Word
and LargeWord
depend on the architecture and represent a machine word. Because SML/NJ does not support 64-bit arch, it has different word size.
You are right in that the types
Word8.word
,Word32.word
andWord64.word
only share the common type'a
which cannot generally be converted aWord64.word
via parametric polymorphism.The exact function you are looking for could (and should) have been:
Unfortunately, as you have discovered, it appears that
LargeWord.word
is an alias toWord32
and notWord64
in SML/NJ. It doesn't look like Basis specifies thatLargeWord.word
must do this, but reality. In Poly/ML it appears thatLargeWord.wordSize
is 126 and in Moscow ML there is noLargeWord
structure! Sigh. But at least in Poly/ML it can contain aWord64.word
.In light of this, I'd suggest one of two things:
You can use ad-hoc polymorphism: Since all three modules share the signature
WORD
and this signature holds, among other things:So a hack may be to convert to a
LargeInt.int
and then down to aWord64.word
: You can build a functor that takes one module with theWORD
signature and return a structure that contains the conversion toWord64
.You can then instantiate this functor for each of your cases:
This is a bit messy and the hierarchy of existing modules that includes
LargeWord
was meant to avoid it.Alternatively, if you'd rather avoid this extra functor and arbitrary-precision integers as an intermediate representation, since this is both inefficient and unnecessary, you could change your standard library's
LargeWord :> WORD
so that it assumes the use ofWord64
instead.This could have been avoided if the standard library had been written in a functorial style with
LargeWord
having/being a parameter fixed somewhere where you could override it. But it would also make the standard library more complex.With regards to ML module system design, I think the choice of placing
toLargeWord
in theWORD
signature is one approach which is very convenient because you don't need a lot of functor instances, but, as you have witnessed, not very extensible. You can see the different philosophies applied in Jane Street's OCaml libraries Base and Core, where in Core you have e.g.Char.Map.t
(convenient) and in Base you haveMap.M(Char).t
(extensible).I've assumed that your words are all unsigned.