हम जब Word8 का उपयोग करने के
GHCi> toTwosComp (1 :: Word8)
*** Exception: divide by zero
ध्यान दें कि यह काम करता है अगर आप Word16 इंट, पूर्णांक, या प्रकार के किसी भी संख्या का उपयोग करें, लेकिन विफल रहता है यह कम कर सकते हैं, के रूप में B.unpack
हमें देता है! तो यह क्यों विफल रहता है? उत्तर source code से Codec.Utils.toTwosComp में पाया गया है। आप देख सकते हैं कि यह toBase 256 (abs x)
पर कॉल करता है, जहां x तर्क है।
toBase
के प्रकार - Codec.Utils मॉड्यूल से निर्यात नहीं किया, और स्रोत में एक स्पष्ट प्रकार हस्ताक्षर के बिना, लेकिन आप एक फाइल में परिभाषा डालने और GHCi किस प्रकार है पूछकर यह देख सकते हैं (:t toBase
) ,,
toBase :: (Integral a, Num b) => a -> a -> [b]
तो है प्रकार स्पष्ट रूप से व्याख्या, toTwosComp
toBase (256 :: Word8) (abs x :: Word8)
बुला रहा है। 256 :: Word8
क्या है?
GHCi> 256 :: Word8
0
ओह! 256> 255, इसलिए हम इसे Word8 में नहीं रोक सकते हैं, और यह चुपचाप बहती है। toBase
, अपने मूल रूपांतरण की प्रक्रिया में, आधार का उपयोग करके विभाजित होता है, इसलिए यह आपके द्वारा प्राप्त किए जा रहे व्यवहार का उत्पादन करके शून्य से विभाजित होता है।
समाधान क्या है? उन्हें toTwosComp
को पार करने से पहले fromIntegral
साथ Ints को Word8s कन्वर्ट:
convert :: B.ByteString -> [Octet]
convert = map convert' . B.unpack
where convert' b = head $ toTwosComp (fromIntegral b :: Int)
व्यक्तिगत रूप से, इस व्यवहार मुझे थोड़ी चिंता है, और मैं, लगता है toTwosComp
शायद इस तरह के एक रूपांतरण ही है, पूर्णांक की संभावना क्या करना चाहिए, ताकि यह साथ काम करता है प्रत्येक आकार के अभिन्न प्रकार; लेकिन यह एक प्रदर्शन जुर्माना होगा कि डेवलपर्स के विचार को पसंद नहीं हो सकता है। फिर भी, यह एक बहुत भ्रमित विफलता है जिसके लिए स्रोत-डाइविंग को समझने की आवश्यकता है। शुक्र है, चारों ओर काम करना बहुत आसान है।
यह 'toTwosComp' में एक बग है। – augustss