Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 为什么这个代码被零除?_Haskell_Divide By Zero - Fatal编程技术网

Haskell 为什么这个代码被零除?

Haskell 为什么这个代码被零除?,haskell,divide-by-zero,Haskell,Divide By Zero,我有一个小Haskell程序,我很好奇为什么在运行它时会抛出一个被零除的异常(GHC 7.0.3) 有人能帮我了解一下这里发生了什么吗?我们可以把它简化为 GHCi> toTwosComp (1 :: Word8) *** Exception: divide by zero 请注意,如果您使用Word16、Int、Integer或任意数量的类型,则此功能有效,但在使用Word8时失败,因为B.unpack为我们提供了!那么为什么它会失败呢?答案可在to中找到。您可以看到它调用了toBas

我有一个小Haskell程序,我很好奇为什么在运行它时会抛出一个被零除的异常(GHC 7.0.3)

有人能帮我了解一下这里发生了什么吗?

我们可以把它简化为

GHCi> toTwosComp (1 :: Word8)
*** Exception: divide by zero
请注意,如果您使用Word16、Int、Integer或任意数量的类型,则此功能有效,但在使用Word8时失败,因为
B.unpack
为我们提供了!那么为什么它会失败呢?答案可在to中找到。您可以看到它调用了
toBase 256(abs x)
,其中x是参数

toBase
的类型-不是从Codec.Utils模块导出的,并且在源代码中没有显式的类型签名,但是您可以通过将定义放入文件并询问GHCi类型(
:t toBase
)来查看

因此,显式注释类型时,
totwoscop
正在调用
toBase(256::Word8)(abs x::Word8)
。什么是
256::Word8

GHCi> 256 :: Word8
0
哎呀!256>255,所以我们无法将其保存在一个字8中,它会无声地溢出
toBase
,在其基址转换过程中,被使用的基址除,因此它最终被零除,产生您得到的行为

解决办法是什么?在将单词8s传递到
totwoscop
之前,使用
from integral
将其转换为整数:

convert :: B.ByteString -> [Octet]
convert = map convert' . B.unpack
  where convert' b = head $ toTwosComp (fromIntegral b :: Int)
就我个人而言,这种行为让我有点担心,我认为
totwoscop
应该自己做这样的转换,很可能是整数,这样它就可以处理各种大小的整数类型;但这将导致性能损失,开发者可能不喜欢这种想法。不过,这是一个相当令人困惑的失败,需要源代码潜水才能理解。谢天谢地,这很容易解决

map (head . toTwosComp) [1, 2, 3, 4]
这段时间很好用

map (head . toTwosComp) $ B.unpack $ B.pack [1, 2, 3, 4]
导致您描述的异常。让我们看看有什么不同

> :t [1, 2, 3, 4]
[1, 2, 3, 4] :: Num t => [t]
> :t unpack $ pack $ [1, 2, 3, 4]
unpack $ pack $ [1,2,3,4] :: [Word8]
Word8可能是导致问题的原因。让我看看

> toTwosComp (1 :: Word8)
*** Exception: divide by zero
显然,我们必须将Word8转换为其他整数类型

> map (head . toTwosComp . fromIntegral) $ B.unpack $ B.pack [1, 2, 3, 4]
[1,2,3,4]

它起作用了

非常有帮助!非常感谢:D
> toTwosComp (1 :: Word8)
*** Exception: divide by zero
> map (head . toTwosComp . fromIntegral) $ B.unpack $ B.pack [1, 2, 3, 4]
[1,2,3,4]