如何在 Haskell 中使记录类型位可寻址?

发布于 2024-11-17 19:40:09 字数 293 浏览 7 评论 0原文

我的记录类型是 4 Word32。

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

大多数时候,我想将这种类型视为4个单独的Word32。然而,有时我希望将其视为单个二进制数据流(128 位长,4 个 Word32 的串联)。我知道在Python中,我会为这个“结构”编写不同的访问器函数,这样我就可以以两种方式读取/修改它。但这是哈斯克尔。我想知道经验丰富的 Haskeller 会如何处理这个问题?

I have a record type that is 4 Word32.

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

Most of the time, I want to treat this type as 4 separate Word32. However, sometimes I wish to treat it as a single stream of binary data (128 bits long, the concatenation of the 4 Word32). I know that in Python, I would write different accessor functions for this "structure", so that I could read/modify it in both ways. But this is Haskell. I am wondering how an experienced Haskeller would go about this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谁的新欢旧爱 2024-11-24 19:40:09

有一个类:-)

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

查看 Data.Bits 文档。完整的最小定义是提供 .&..|.complementshift 的实现、 rotatebitSizeisSigned (或其他一些可能的组合:有关详细信息,请参阅文档)。令人烦恼的是,您还必须实现 Num,尽管我并不完全清楚为什么他们要这样定义它。

There's a class for that :-)

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

Check out the documentation for Data.Bits. A complete minimal definition is to provide an implementation of .&., .|., complement, shift, rotate, bitSize and isSigned (or a few other possible combinations: see the doc for details). Annoyingly you also have to implement Num, although it's not entirely clear to me why they defined it that way.

够钟 2024-11-24 19:40:09

如果你真的希望它像一个由四个 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

然后 abc d 字段,您可以使用 fclabels。您还可以创建一个 fclabel 双射函子 (:<->:)

myType128 :: MyType :<->: Integer
myType128 = to128 :<->: from128

If you really want it to be like a struct of four word32's, you might want to use strict/unpacked fields:

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

Then, let's define a couple of bit-fiddling functions:

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

Now you can just write 128-bit accessors for this type:

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

For the a b c d fields, you can just use fclabels. You can also make an fclabel bijective Functor (:<->:):

myType128 :: MyType :<->: Integer
myType128 = to128 :<->: from128
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文