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.wordandWord64.wordonly share the common type'awhich cannot generally be converted aWord64.wordvia parametric polymorphism.The exact function you are looking for could (and should) have been:
Unfortunately, as you have discovered, it appears that
LargeWord.wordis an alias toWord32and notWord64in SML/NJ. It doesn't look like Basis specifies thatLargeWord.wordmust do this, but reality. In Poly/ML it appears thatLargeWord.wordSizeis 126 and in Moscow ML there is noLargeWordstructure! 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
WORDand this signature holds, among other things:So a hack may be to convert to a
LargeInt.intand then down to aWord64.word: You can build a functor that takes one module with theWORDsignature 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
LargeWordwas 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 :> WORDso that it assumes the use ofWord64instead.This could have been avoided if the standard library had been written in a functorial style with
LargeWordhaving/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
toLargeWordin theWORDsignature 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.