Полиморфное приведение к Word64 в Standard ML
Я хотел бы создать полиморфную функцию, которая преобразует 8,16,32-битные слова в 64-битное слово. Как мне это сделать?
Update1
В базовой библиотеке все структуры слов имеют функции toLarge
а также fromLarge
конвертировать в / из LargeWord
Насколько я понимаю, это просто синоним Word32.
UPDATE2
Согласно спецификации, размер слова должен быть степенью двойки, но в 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?
Update3
На самом деле, я хочу иметь возможность "переводить" более мелкие слова в более крупные с помощью оператора (<<), но не могу понять, как это сделать.
UPDATE4
Кажется, что Word
а также LargeWord
зависит от архитектуры и представляет собой машинное слово. Поскольку SML/NJ не поддерживает 64-битную арку, он имеет другой размер слова.
2 ответа
Вы правы в том, что типы Word8.word
, Word32.word
а также Word64.word
делиться только общим типом 'a
который обычно не может быть преобразован Word64.word
через параметрический полиморфизм.
Точная функция, которую вы ищете, могла (и должна была) быть:
Word<N>.toLargeWord : word -> LargeWord.word
К сожалению, как вы обнаружили, похоже, что LargeWord.word
псевдоним Word32
и не Word64
в SML/NJ. Это не похоже, что Базис указывает, что LargeWord.word
должен сделать это, но реальность. В Poly/ML кажется, что LargeWord.wordSize
это 126 а в москве мл нет LargeWord
состав! Вздох. Но, по крайней мере, в Poly/ML он может содержать Word64.word
,
В свете этого я бы предложил одну из двух вещей:
Вы можете использовать специальный полиморфизм: поскольку все три модуля имеют общую подпись
WORD
и эта подпись содержит, среди прочего:val toLargeInt : word -> LargeInt.int
Таким образом, взлом может быть преобразовать в
LargeInt.int
а затем до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
должен был избежать этого.В качестве альтернативы, если вы предпочитаете избегать использования этого дополнительного функтора и целых чисел произвольной точности в качестве промежуточного представления, поскольку это неэффективно и не нужно, вы можете изменить стандартную библиотеку.
LargeWord :> WORD
так что предполагает использованиеWord64
вместо.
Этого можно было бы избежать, если бы стандартная библиотека была написана в стиле функториала с LargeWord
имея / будучи фиксированным параметром где-нибудь, где вы можете переопределить его. Но это также сделает стандартную библиотеку более сложной.
Что касается дизайна системы модулей ML, я думаю, что выбор размещения toLargeWord
в WORD
Сигнатура - это один из подходов, который очень удобен, потому что вам не нужно много экземпляров функторов, но, как вы видели, не очень расширяемый. Вы можете увидеть различные философии, применяемые в библиотеках OCaml Base и Core Джейн Стрит, где в Core у вас есть, например, Char.Map.t
(удобно) и в базе у вас есть Map.M(Char).t
(Расширяемый).
Я предположил, что ваши слова все без знака.
Я пришел к выводу, что нет способа сделать это полиморфным способом. Вместо этого нужно использовать соответствующий toLarge/fromLarge
методы как это:
fun toWord64 (w : Word8.word) : Word64.word = Word64.fromLarge (Word8.toLarge w)
Я мог бы использовать toLarge
напрямую, но я хочу убедиться, что полученное значение будет Word64
, Это скомпилируется с SML/NJ, но вызов этой функции вызовет исключение во время выполнения.
Кстати, я не нашел способа извлечь Word64 из байтового массива в 32-битном SML/NJ.