1

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

更新1

在基础库中,所有单词结构都具有功能toLargefromLarge可以转换为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

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

更新4

似乎WordLargeWord取决于架构并代表一个机器字。因为 SML/NJ 不支持 64 位 arch,所以它有不同的字长。

4

2 回答 2

2

你是对的,类型Word8.wordWord32.word并且Word64.word只共享通常不能通过参数多态性'a转换的通用类型。Word64.word

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

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

不幸的是,正如您所发现的,它似乎LargeWord.word是 SML/NJ 的别名,Word32而不是Word64SML/NJ 的别名。看起来Basis并没有指定LargeWord.word 必须这样做,而是现实。在 Poly/ML 中显示LargeWord.wordSize为 126,而在莫斯科 ML 中没有LargeWord结构!叹。但至少在 Poly/ML 中它可以包含一个Word64.word.

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

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

    val toLargeInt : word -> LargeInt.int
    

    所以一个hack可能是先转换为a LargeInt.int,然后再转换为a Word64.word:您可以构建一个函子,该函子采用一个带有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是为了避免它。

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

如果标准库是以函数式风格编写的,LargeWord并且将参数固定在可以覆盖它的某个地方,则可以避免这种情况。但这也会使标准库更加复杂。

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

我假设你的话都没有签名。

于 2018-12-04T08:05:00.567 回答
1

我得出的结论是,没有办法以多态方式实现这一点。相反,必须使用这样的适当toLarge/fromLarge方法:

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

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

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

于 2018-12-03T10:02:30.963 回答