繁体   English   中英

如何在无符号类型(例如,Word8,Word16)上使用Haskell的按位函数?

[英]How to use Haskell's bitwise functions on unsigned types (e.g., `Word8`, `Word16`)?

为了能够对无符号类型(即Word8Word16 )使用Data.Bits函数(例如, clearBitsetBit ),我该怎么做? 此刻,我收到以下错误:

Couldn't match expected type ‘Int’ with actual type ‘Word8’

我将要执行大量此类操作,因此fromIntegral并不理想。

有什么建议么?

更新2:这是我需要的:

testBitW :: (Bits a, Integral b) => a -> b -> Bool
testBitW a i = testBit a (fromIntegral i)

更新:

我正在拔头发,试图汇编以下内容。 令人费解的是,如果直接输入GHCi,则相同的代码可以正常工作(运行:t给出的隐式类型签名与下面的定义相同)。

testBitW :: (Integral a, Integral b) => a -> b -> Bool
testBitW a i = testBit (fromInteger $ toInteger a) (fromInteger $ toInteger i)

我不断收到以下两个错误。 使用fromIntegral代替fromInteger $ toInteger导致相同的错误...

test.hs:119:16:
    Could not deduce (Bits a0) arising from a use of ‘testBit’
    from the context (Integral a1, Integral a)
      bound by the inferred type of
               testBitW :: (Integral a1, Integral a) => a -> a1 -> Bool
      at test.hs:119:1-78
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance Bits Word16 -- Defined in ‘GHC.Word’
      instance Bits Word32 -- Defined in ‘GHC.Word’
      instance Bits Word64 -- Defined in ‘GHC.Word’
      ...plus 9 others
    In the expression:
      testBit (fromInteger $ toInteger a) (fromInteger $ toInteger i)
    In an equation for ‘testBitW’:
        testBitW a i
          = testBit (fromInteger $ toInteger a) (fromInteger $ toInteger i)

test.hs:119:25:
    Could not deduce (Num a0) arising from a use of ‘fromInteger’
    from the context (Integral a1, Integral a)
      bound by the inferred type of
               testBitW :: (Integral a1, Integral a) => a -> a1 -> Bool
      at test.hs:119:1-78
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance Num Double -- Defined in ‘GHC.Float’
      instance Num Float -- Defined in ‘GHC.Float’
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in ‘GHC.Real’
      ...plus 11 others
    In the expression: fromInteger
    In the first argument of ‘testBit’, namely
      ‘(fromInteger $ toInteger a)’
    In the expression:
      testBit (fromInteger $ toInteger a) (fromInteger $ toInteger i)
Failed, modules loaded: none.

导入Data.Word会将Bits Word8等的实例纳入范围。

尽管从您的错误看来,您似乎正在谈论setBit的第二个参数,该参数指定为Int 如果要使用Word指定位偏移,则必须使用fromInteger . toInteger fromInteger . toInteger 您可以根据上下文以某种方式抽象出来。

更新资料

在这种情况下,“无法推断...”形式的错误是编译器强烈提示的有关所需类型签名的信息。 这是解决问题的方法。

首先, testBit的类型是testBit

> :t testBit
testBit :: Bits a => a -> Int -> Bool

因此我们知道第二个参数需要是一个Int (而不是Integer !),但是第一个参数可以是具有Bits实例的任何类型。 最通用的Int转换是通过Integer

> :t \x -> (fromInteger . toInteger $ x) :: Int
\x -> (fromInteger . toInteger $ x) :: Int
  :: Integral s => s -> Int

因此,我们需要了解我们testBitW函数的每个参数的一件事:第一个需要是Bits的实例,第二个需要Integral的实例。 (我们并不需要的第一个参数转换为Int ,而事实上这样做几乎可以肯定是一个错误。)

如有疑问,我们可以让编译器推断约束,这通常会为您提供最通用的类​​型签名:

> let testBitW a i = testBit a (fromInteger . toInteger $ i)
> :t testBitW
testBitW :: (Bits a, Integral s) => a -> s -> Bool

这就是要放在源文件中的类型签名。

第二个代码段不起作用的原因是,您没有(... Bits a, Bits b) =>作为约束的一部分。 Integral并不意味着Bits 在这种情况下,您也根本不需要转换第一个参数,而只需要fromIntegral作为第二个参数(例如您的第一个代码段)。

testBit要求其第一个参数的类型为Bits的实例,并且您不能从Integral约束中确定这一点,因为这两个类型类实质上是彼此独立的。

另外,我怀疑fromIntegral调用中的那些将具有最小的运行时成本。

顺便说一下, fromIntegral 定义为

fromIntegral :: (Integral a, Num b) => a -> b
fromIntegral = fromInteger . toInteger

虽然,有RULES ,以优化该定义了一些常见的情况和有更多fromIntegral RULES ,在这些特殊情况下GHC.Word (其由导入的Data.Word )。

我相信代码在GHCi中起作用的原因是这部分(fromInteger $ toInteger a)默认为更特定的类型。 GHCi比GHC具有更积极的类型默认设置(尤其是对于此类数字类型)。 如果我在GHCi中使用default ()禁用了数字默认default () ,然后尝试按照第二个示例中的定义定义testBitW ,看起来它给出了相同的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM