Полиморфное приведение к Word64 в Standard ML - PullRequest
0 голосов
/ 03 декабря 2018

Я хотел бы создать полиморфную функцию, которая преобразует 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

На самом деле, я хочу иметь возможность "переводить" более мелкие слова в более крупные, используя оператор (<<), но не могупонять, как это сделать. </p>

UPDATE4

Кажется, что Word и LargeWord зависят от архитектуры и представляют собой машинное слово.Поскольку SML / NJ не поддерживает 64-битную арку, он имеет другой размер слова.

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Вы правы в том, что типы Word8.word, Word32.word и Word64.word имеют только общий тип 'a, который обычно не может быть преобразован в Word64.word через параметрический полиморфизм .

Точная функция, которую вы ищете может должен ) была:

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

К сожалению, как вы обнаружили, кажется, чтоLargeWord.word - это псевдоним Word32, а не Word64 в SML / NJ.Не похоже, что Basis указывает, что LargeWord.word должен сделать это, но реальность.В Poly / ML похоже, что LargeWord.wordSize - 126, а в московском ML нет структуры LargeWord!Вздох.Но, по крайней мере, в Poly / ML он может содержать Word64.word.

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

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

  2. В качестве альтернативы, если вы предпочитаете избегать использования этого дополнительного функтора и целых чисел произвольной точности в качестве промежуточного представления, поскольку это неэффективно и не нужно, вы можете изменить стандартную библиотеку LargeWord :> WORD так что предполагается использование Word64 вместо.

Этого можно было бы избежать, если бы стандартная библиотека была написана в стиле функториала с LargeWord, имеющим / являющимся фиксированным параметром где-то, где вы могли бы переопределить его.Но это также сделало бы стандартную библиотеку более сложной.

Что касается конструкции системы модулей ML, я думаю, что выбор размещения toLargeWord в сигнатуре WORD является одним из подходов, который очень удобен, потому что вы нене нужно много экземпляров функторов, но, как вы видели, не очень расширяемых.Вы можете увидеть различные философии, применяемые в библиотеках OCaml Base и Core Джейн Стрит, где в Core у вас есть, например, Char.Map.t (удобно), а в Base у вас есть Map.M(Char).t (расширяемый).

IПредполагается, что все ваши слова без знака.

0 голосов
/ 03 декабря 2018

Я пришел к выводу, что нет способа сделать это полиморфным способом.Вместо этого нужно использовать соответствующие toLarge/fromLarge методы, подобные этому:

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

Я мог бы использовать toLarge напрямую, но я хочу убедиться, что полученное значение будет Word64.Это скомпилируется с SML / NJ, но вызов этой функции вызовет исключение во время выполнения.

Кстати, я не нашел способа извлечь Word64 из байтового массива в 32-битном SML / NJ.

...