我想创建一个将8、16、32位字转换为64位字的多态函数。我该怎么办?
在基础库中,所有单词结构都具有函数toLarge
和fromLarge
来与LargeWord
进行相互转换,据我所知,这只是Word32的同义词。
根据规范,字长必须为2的幂,但是在SML / NJ中我有
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
在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
那怎么样?为什么Word.wordSize
不是2的幂?为什么Word
表示在这些SML实现中有所不同?
实际上,我希望能够使用(<<)运算符将较小的单词“提升”为较大的单词,但无法弄清楚该怎么做。
似乎Word
和LargeWord
取决于体系结构,代表一个机器字。由于SML / NJ不支持64位arch,因此其字长有所不同。
答案 0 :(得分:2)
您是正确的,因为类型Word8.word
,Word32.word
和Word64.word
仅共享公用类型'a
,通常不能通过<转换为Word64.word
em>参数多态性。
您正在寻找的可能(和应该)的确切功能是:
Word<N>.toLargeWord : word -> LargeWord.word
不幸的是,正如您所发现的,似乎LargeWord.word
是Word32
的别名,而不是SML / NJ中的Word64
的别名。看起来 Basis 并没有指定LargeWord.word
必须这样做,但实际上是这样。在Poly / ML中,看来LargeWord.wordSize
是126,而在Moscow ML中则没有LargeWord
结构!叹。但是至少在Poly / ML中,它可以包含Word64.word
。
鉴于此,我建议以下两件事之一:
您可以使用临时多态性:由于所有三个模块共享签名WORD
,并且该签名除其他事项外,还保留:
val toLargeInt : word -> LargeInt.int
因此,黑客可能会先转换为LargeInt.int
,然后再转换为Word64.word
:您可以构建一个使用{{1} }签名并返回一个包含到WORD
的转换的结构。
Word64
然后您可以为每种情况实例化此仿函数:
functor ToWord64 (WordN : WORD) = struct
fun toWord64 (n : WordN.word) : Word64.word =
Word64.fromLargeInt (WordN.toLargeInt n)
end
这有点混乱,而包含structure Word8ToWord64 = ToWord64(Word8)
val myWord64 = Word8ToWord64.toWord64 myWord8
的现有模块的层次结构就是为了避免这种情况。
或者,如果您希望避免使用此多余的函子和任意精度整数作为中间表示,则由于这既效率低下又不必要,则可以更改标准库的LargeWord
,使其假定改为使用LargeWord :> WORD
。
如果标准库是使用Word64
的函子样式编写的,则在某个可以覆盖它的地方固定/固定了参数,可以避免这种情况。但这也会使标准库更加复杂。
关于ML模块系统设计,我认为选择在LargeWord
签名中放置toLargeWord
是一种非常方便的方法,因为您不需要很多函子实例,但是如您所见,不是很可扩展。您可以在Jane Street的OCaml库Base和Core中看到应用的不同原理,在Core中,例如WORD
(方便),在Base中您有Char.Map.t
(可扩展)。
我假设您的单词都是未签名的。
答案 1 :(得分:1)
我得出的结论是,没有办法以多态的方式做到这一点。相反,必须使用适当的toLarge/fromLarge
方法,如下所示:
fun toWord64 (w : Word8.word) : Word64.word = Word64.fromLarge (Word8.toLarge w)
我可以直接使用toLarge
,但是我想确保结果值为Word64
。这将使用SML / NJ进行编译,但是调用此函数将导致运行时异常。
顺便说一句,我没有找到如何从32位SML / NJ的字节数组中提取Word64的方法。