标准ML中Word64的多态强制

时间:2018-12-03 08:29:24

标签: sml smlnj polyml mlton

我想创建一个将8、16、32位字转换为64位字的多态函数。我该怎么办?

UPDATE1

在基础库中,所有单词结构都具有函数toLargefromLarge来与LargeWord进行相互转换,据我所知,这只是Word32的同义词。

UPDATE2

根据规范,字长必须为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实现中有所不同?

UPDATE3

实际上,我希望能够使用(<<)运算符将较小的单词“提升”为较大的单词,但无法弄清楚该怎么做。

UPDATE4

似乎WordLargeWord取决于体系结构,代表一个机器字。由于SML / NJ不支持64位arch,因此其字长有所不同。

2 个答案:

答案 0 :(得分:2)

您是正确的,因为类型Word8.wordWord32.wordWord64.word仅共享公用类型'a,通常不能通过<转换为Word64.word em>参数多态性。

您正在寻找的可能(和应该)的确切功能是:

Word<N>.toLargeWord : word -> LargeWord.word

不幸的是,正如您所发现的,似乎LargeWord.wordWord32的别名,而不是SML / NJ中的Word64的别名。看起来 Basis 并没有指定LargeWord.word 必须这样做,但实际上是这样。在Poly / ML中,看来LargeWord.wordSize是126,而在Moscow ML中则没有LargeWord结构!叹。但是至少在Poly / ML中,它可以包含Word64.word

鉴于此,我建议以下两件事之一:

  1. 您可以使用临时多态性:由于所有三个模块共享签名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 的现有模块的层次结构就是为了避免这种情况。

  2. 或者,如果您希望避免使用此多余的函子和任意精度整数作为中间表示,则由于这既效率低下又不必要,则可以更改标准库的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的方法。