标准 ML 中 Word64 的多态转换

Polymorphic coersion to Word64 in Standard ML

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

更新 1

在基础库中,所有的词结构都有函数toLargefromLarge将to/from转换为LargeWord,据我所知只是一个同义词Word32.

更新2

根据规范,字长必须是 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 不是二的幂?为什么 Word 表示在这些 SML 实现中不同?

更新3

实际上,我希望能够使用 (<<) 运算符 "promote" 将较小的单词转换为较大的单词,但不知道该怎么做。

更新4

好像WordLargeWord依赖架构,代表一个机器字。因为SML/NJ不支持64位arch,所以字长不同

我的结论是,没有办法以多态方式实现它。相反,必须使用适当的 toLarge/fromLarge 方法,如下所示:

fun toWord64 (w : Word8.word) : Word64.word = Word64.fromLarge (Word8.toLarge w)

我可以直接使用 toLarge,但我想确保结果值为 Word64。这将使用 SML/NJ 进行编译,但调用此函数将导致运行时异常。

顺便说一句,我没有找到如何从 32 位字节数组中提取 Word64 的方法SML/NJ。

你说得对,类型 Word8.wordWord32.wordWord64.word 仅共享通用类型 'a,通常不能转换为 Word64.word通过 参数多态性 .

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

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.

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

  1. 您可以使用 ad-hoc 多态性:因为所有三个模块共享签名 WORD 并且此签名持有,除其他外:

    val toLargeInt : word -> LargeInt.int
    

    所以一个 hack 可能是转换为 LargeInt.int,然后向下转换为 Word64.word:您可以构建一个 functor,它需要一个模块WORD 签名和 return 包含转换为 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 的现有模块的层次结构旨在避免它。

  2. 或者,如果您希望避免使用这种额外的函子和任意精度整数作为中间表示,因为这既低效又不必要,您可以更改标准库的 LargeWord :> WORD所以它假定使用 Word64 代替。

如果标准库是用函数式风格编写的,并且 LargeWord having/being 参数固定在某个地方,您可以覆盖它,这本可以避免。但它也会使标准库更加复杂。

关于 ML 模块系统设计,我认为选择将 toLargeWord 放在 WORD 签名中是一种非常方便的方法,因为您不需要很多仿函数实例,但是,正如您所见,不是很可扩展。您可以看到 Jane Street 的 OCaml 库 Base 和 Core 中应用的不同哲学,在 Core 中您有例如Char.Map.t(方便),在 Base 中你有 Map.M(Char).t(可扩展)。

我假设你的话都是无符号的