Полиморфное приведение к 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,

В свете этого я бы предложил одну из двух вещей:

  1. Вы можете использовать специальный полиморфизм: поскольку все три модуля имеют общую подпись 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 должен был избежать этого.

  2. В качестве альтернативы, если вы предпочитаете избегать использования этого дополнительного функтора и целых чисел произвольной точности в качестве промежуточного представления, поскольку это неэффективно и не нужно, вы можете изменить стандартную библиотеку. 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.

Другие вопросы по тегам