Nano Hash - криптовалюты, майнинг, программирование

Как сделать бит типа записи адресуемым в Haskell?

У меня есть тип записи 4 Word32.

data MyType = MyType {a :: Word32, b :: Word32, c :: Word32, d :: Word32 }

В большинстве случаев я хочу рассматривать этот тип как 4 отдельных Word32. Однако иногда я хочу рассматривать его как единый поток двоичных данных (длиной 128 бит, конкатенация 4 Word32). Я знаю, что в Python я бы написал разные функции доступа для этой «структуры», чтобы я мог читать/изменять ее обоими способами. Но это Хаскель. Мне интересно, как бы поступил с этим опытный Haskeller?


  • Я чувствую, что, возможно, мне следует уточнить, чего я хочу. Мне нужна возможность иметь тип, который в основном представляет собой 128-битное слово (без знака). Однако мне также нужна возможность извлекать a (биты 127-96), b (биты 95-64), c (биты 63-32) и d (биты 31-0). Я думаю, что могу написать функции для a, b, c, d, но я не знаю, как создать простое 128-битное слово (при условии, что так и должно быть). Извиняюсь за отсутствие ясности, любая помощь приветствуется. 01.07.2011

Ответы:


1

Если вы действительно хотите, чтобы это было похоже на структуру из четырех word32, вы можете использовать строгие/распакованные поля:

data MyType = MyType { a :: {-# UNPACK #-} !Word32
                     , b :: {-# UNPACK #-} !Word32
                     , c :: {-# UNPACK #-} !Word32
                     , d :: {-# UNPACK #-} !Word32 }
  deriving (Show)

Затем давайте определим пару функций для работы с битами:

mask :: Bits a => Int -> a
mask count = (1 `shiftL` count) - 1

bitRange :: Bits a => Int -> Int -> a -> a
bitRange low count val = (val `shiftR` low) .&. mask count

Теперь вы можете просто написать 128-битные аксессоры для этого типа:

from128 :: Integer -> MyType
from128 val = MyType (bitsFrom 0)
                     (bitsFrom 32)
                     (bitsFrom 64)
                     (bitsFrom 96)
  where
    bitsFrom i = fromIntegral (bitRange i 32 val)

to128 :: MyType -> Integer
to128 (MyType a b c d) =
  foldl' (.|.) 0 [
    bitsTo a 0,
    bitsTo b 32,
    bitsTo c 64,
    bitsTo d 96
  ]
  where
    bitsTo val i = fromIntegral val `shiftL` i

Для полей a b c d вы можете просто использовать fclabels. Вы также можете сделать fclabel биективным Functor (:<->:):

myType128 :: MyType :<->: Integer
myType128 = to128 :<->: from128
30.06.2011
  • Спасибо, здесь есть по крайней мере от 4 до 6 вещей, которые я на самом деле не понимаю. Я постараюсь понять это самостоятельно, построчно. Но я очень ценю, что вы дали мне еще один (реализованный) способ сделать это! 01.07.2011
  • @Stephen: я был бы рад объяснить вам любой вопрос об этом коде. 01.07.2011
  • {-# UNPACK #-} и что именно делает Word32? Unpack, кажется, говорит компилятору встроить значение, а не использовать конструктор значений? Если это так, что делает !Word32? 01.07.2011
  • foldl' (.|.) 0 ... Что делает выглядящая (.|.) штука? Я начинаю с 0, как он сдвигает значения, чтобы они добавлялись правильно? 01.07.2011
  • В ссылке fclabels есть $(mkLabels [''Person, ''Place]). Что означает '' перед лицом или местом, что это значит? 01.07.2011
  • Я понятия не имею, что такое биективный функтор, если только это не название группы или что-то в этом роде. 01.07.2011
  • {-# UNPACK #-} — это прагма-директива для компилятора, предписывающая ему распаковать поля word32, чтобы они сохранялись непосредственно как поля Word32, точно так же, как в C или C++. Обычно они будут храниться с оберткой коробки (что допускает лень/и т. д. Это не конструктор значений). ! префикс к типу говорит, что поле является строгим полем - что при вычислении значения MyType это поле должно быть вычислено немедленно. 03.07.2011
  • (.|.) — это оператор побитового ИЛИ. Он принимает два двоичных числа и делает что-то вроде zipWith (||) для их битов. Таким образом, 5 .|. 2 будет (двоичным) 101 .|. 010 и результат 111, что равно 7. Короче говоря: 5 .|. 2 == 7. Складка в основном берет числа, сдвигает их в правильное положение, а затем подставляет их к результирующему числу. 03.07.2011
  • '' — это нотация TemplateHaskell, используемая для обозначения конструкторов типов. Person и Place будут ссылаться на конструкторы данных по этим именам, но «Person» и «Place» ссылаются на конструкторы типов с этими именами. 03.07.2011
  • @StephenCagle позвольте нам продолжить это обсуждение в чате 03.07.2011

  • 2

    Для этого есть класс :-)

    import Data.Bits
    
    newtype MyWord128 = MyWord128 MyType
    
    instance Num MyWord128 where
       -- implement this one
    
    instance Bits MyWord128 where
       -- and then this one, which is what you really want
    

    Ознакомьтесь с документацией по данным. Биты. Полное минимальное определение должно предоставить реализацию .&., .|., complement, shift, rotate, bitSize и isSigned (или несколько других возможных комбинаций: подробности см. в документе). Досадно, что вам также нужно реализовать Num, хотя мне не совсем понятно, почему они определили это именно так.

    30.06.2011
  • Возвращаясь к этому вопросу, потому что я сталкивался с ним раньше: как бы вы эффективно реализовали, скажем, сдвиг и вращение? Точнее, мне бы очень хотелось иметь возможность сказать «получить Word32 в позицию N», что в C было бы простым смещением указателя, но в Haskell я не вижу альтернативы написанию оператора case, что не ахти. (Или использовать массивы, которые не имеют фиксированного размера и имеют другие накладные расходы.) 30.06.2011
  • Вам не нужно использовать новый тип MyWord128, вы можете просто сделать MyType экземпляром Bits. Эффективно ли это — другая история. Реализация MyType поверх Storage и использование сырой памяти плюс некоторый код FFI to C может быть наиболее эффективным способом. 30.06.2011
  • Re: новый тип. В последнее время я экспериментирую с созданием экземпляров только для базового базового типа данных, когда я могу придумать единственный недвусмысленный способ реализации экземпляра. В этом случае я могу думать как минимум о двух (с прямым порядком байтов или с прямым порядком байтов). Отсюда и новый тип. 30.06.2011
  • Ничего себе, я проголосовал за вас, но это кажется значительным объемом работы для того, что я хочу. Все, что я действительно хочу, это иметь возможность получить диапазон (startingBitIndex, EndingBitIndex) битов из MyWord 128. Однако похоже, что для использования Data.Bits мне пришлось бы реализовать все минимальное определение Num и Data.Bits ? Это правильно? 01.07.2011
  • Если на то пошло, можно ли просто создать 128-битное слово. Если бы у меня было это, я мог бы просто написать набор из четырех функций, которые позволили бы мне вытащить a, b, c, d? Может намного проще? 01.07.2011
  • @StephenCagle: криптобиблиотека имеет тип данных Word128, к сожалению, это довольно большая зависимость только для одного типа данных. Я ищу более приятный способ получить Word128 самостоятельно. Возможно, подойдет библиотека Data.LargeWord ;). В качестве альтернативы, согласно ответу Пикера, Integer легко вмещает 128 бит, но это не фиксированный размер. 31.07.2011
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..