我可以做些什么(如果有的话),以便能够使用Data.Bits
(例如clearBit
,setBit
)中无符号类型的函数,即Word8
和Word16
?目前,我收到以下错误:
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.
答案 0 :(得分:3)
导入Data.Word
会将Bits Word8
等实例纳入范围。
虽然从您的错误中看起来您正在谈论第二个参数,例如setBit
,指定为Int
。如果要使用Word
s指定位偏移量,则必须使用fromInteger . toInteger
。您可以根据上下文以某种方式抽象出来。
在这种情况下,表单“无法推断......”的错误是编译器关于所需类型签名的强提示。以下是如何解决这个问题。
首先,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
这是放在源文件中的类型签名。
答案 1 :(得分:2)
第二个代码段不起作用的原因是您没有(... Bits a, Bits b) =>
作为约束的一部分。 Integral
并不意味着Bits
。在这种情况下,您根本不需要转换第一个参数,只需要fromIntegral
作为第二个参数(就像您的第一个代码片段一样)。
testBit
要求其第一个参数属于Bits
的实例类型,并且您无法从Integral
约束中确定,因为这两个类型类基本上是独立的彼此。
此外,我怀疑这些fromIntegral
次呼叫的运行时间成本最低。
顺便说一下,fromIntegral
是defined as:
fromIntegral :: (Integral a, Num b) => a -> b
fromIntegral = fromInteger . toInteger
虽然RULES
有fromIntegral
优化了一些常见案例的定义,GHC.Word
中的RULES
Data.Word
更多(fromInteger $ toInteger a)
default ()
{1}})。
我相信代码在GHCi中工作的原因是这部分testBitW
默认为更具体的类型。 GHCi比GHC具有更积极的类型默认(特别是对于像这样的数字类型)。如果我使用{{1}}禁用GHCi中的数字默认值,然后尝试在第二个示例中定义{{1}},则看起来它会出现相同的错误。