簡體   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