问题
I can't find a function addWithCarry :: Word8 -> Word8 -> (Word8, Bool)
already defined in base
. The only function documented as caring about carries seems to be addIntC#
in GHC.Prim
but it seems to never be pushed upwards through the various abstraction layers.
I could obviously roll out my own by testing whether the output value is in range and it's in fact what I am currently doing but I'd rather reuse an (potentially more efficient) already defined one.
Is there such a thing?
回答1:
If you look at the source for Word8's Num instance, you'll see that everything is done by converting to a Word#
unboxed value and performing operations on that, and then narrowing down to a 8-bit value. I suspected that doing comparison on that Word#
value would be more efficient, so I implemented such a thing. It's available on lpaste (which I find easier to read than StackOverflow).
Note that it includes both a test suite and Criterion benchmark. On my system, all of the various tests take ~31ns for the boxed version (user5402's implementation) and ~24ns for the primops versions.
The important function from the lpaste above is primops
, which is:
primops :: Word8 -> Word8 -> (Word8, Bool)
primops (W8# x#) (W8# y#) =
(W8# (narrow8Word# z#), isTrue# (gtWord# z# 255##))
where
z# = plusWord# x# y#
回答2:
A way to do this is:
addWithCarry :: Word8 -> Word8 -> (Word8, Bool)
addWithCarry x y = (z, carry)
where z = x + y
carry = z < x
来源:https://stackoverflow.com/questions/27204425/add-with-carry-on-word8