I am attempting to follow up on How to convert a Integer to a ByteString in Haskell. My objective is to create a function toBytes :: Integer -> Int -> ByteString
which returns a big-endian encoding of the magnitude of a potentially large Integer
. The resulting ByteString
(lazy or strict I am not too sure yet) should be of length indicated by the Int
argument. In essence, I would like to replicate the semantics of the python
call (assuming value
is a non-negative integer):
value.to_bytes(numBytes, byteorder='big', signed=False)
I do not need to have everything spelt out of course, I am only looking for guidance. For example, I would be very happy to have anything which brings me closer to my end goal with related semantics such java
's toByteArray
method on BigInteger
(big-endian, two's complement, minimal size) or C#
's ToByteArray
on BigInteger
(little-endian, two's complement, minimal size). I can take care of endianness, and negative number, and add whatever padding is required...
The post I have indicated recommends packages such as Data.Binary
and Data.Serialize
but the encode
function does not seem to follow a clear encoding standard:
Prelude Data.Binary> encode (0xfffefd :: Integer)
"\NUL\NUL\255\254\253"
Prelude Data.Binary> encode (0xfffefdfc :: Integer)
"\SOH\SOH\NUL\NUL\NUL\NUL\NUL\NUL\NUL\EOT\252\253\254\255"
The type of encoding seems to change as the Integer
gets larger, going from big-endian to little-endian for example. So I am wondering, whether it is a wise choice for me to try and build my own function on top of the encode
function provided by these packages. I worry my code will rely on implementation details which may be specific to my host endianness and/or package version.
I am only doing this because I want to learn Haskell
. So as a simple exercise, I am attempting to create a type with the same API as java
's BigInteger
(albeit with a better toByteArray
):
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import qualified Data.ByteString.Lazy as L
import Data.Hashable
type ByteArray = L.ByteString
newtype Sign = Sign Int
newtype NumBytes = NumBytes Int
newtype Number = Number Integer
deriving (Eq, Ord, Num, Real, Enum, Integral, Hashable)
fromBytes :: Sign -> ByteArray -> Number
toBytes :: Number -> NumBytes -> ByteArray
Any guidance is warmly appreciated