diff --git a/CHANGELOG.md b/CHANGELOG.md index 940466f..b19eb90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ Bugfixes: Other improvements: +- `UInt64.unsafeFromInt` (#5 by @jamesdbrock) +- `newtype` wrappers for `Int64`, `UInt64` (#5 by @jamesdbrock) + ## [v1.0.0](https://github.com/purescript-contrib/purescript-int64/releases/tag/v1.0.0) - 2022-05-07 Initial release. diff --git a/spago-dev.dhall b/spago-dev.dhall index 16eea5a..1f29099 100644 --- a/spago-dev.dhall +++ b/spago-dev.dhall @@ -13,7 +13,6 @@ conf // { sources = [ "src/**/*.purs", "test/**/*.purs", ] , dependencies = conf.dependencies # [ "spec" - , "psci-support" , "aff" , "quickcheck-laws" , "assert" diff --git a/spago.dhall b/spago.dhall index 7ed6717..9843d5e 100644 --- a/spago.dhall +++ b/spago.dhall @@ -8,6 +8,7 @@ , "functions" , "maybe" , "quickcheck" + , "unsafe-coerce" ] , packages = ./packages.dhall , sources = [ "src/**/*.purs", ] diff --git a/src/Data/Int64.purs b/src/Data/Int64.purs index c67a6ac..67b7b17 100644 --- a/src/Data/Int64.purs +++ b/src/Data/Int64.purs @@ -1,9 +1,7 @@ -- | Signed two’s-complement 64-bit integers and operations. -- | -- | All of the usual arithmetic operations are supplied by typeclass --- | instances from typeclasses in the __Prelude__. --- | --- | The `Show` instance will suffix a lowercase ‘l’ for “long”. +-- | instances. -- | -- | #### Usage -- | @@ -46,9 +44,9 @@ -- | 23 -- | ``` module Data.Int64 - ( module R - , fromLowHighBits + ( Int64 , fromInt + , fromLowHighBits , fromNumber , fromString , fromStringAs @@ -64,6 +62,7 @@ module Data.Int64 , quot , rem , toUnsigned + , toSigned , and , (.&.) , or @@ -76,121 +75,145 @@ module Data.Int64 , complement ) where -import Data.Int (Parity, Radix) -import Data.Int64.Internal (Int64) as R -import Data.Int64.Internal (Int64, UInt64) +import Prelude + +import Data.Int (Parity, Radix, decimal) import Data.Int64.Internal as Internal import Data.Maybe (Maybe) +import Data.UInt64 (UInt64) +import Test.QuickCheck (class Arbitrary) +import Unsafe.Coerce (unsafeCoerce) + +-- | Signed two’s-complement 64-bit integer. +newtype Int64 = Int64 (Internal.Long' Internal.Signed) + +-- | The `Show` instance will suffix a lowercase ‘l’ for “long”. +-- | (See `toString`.) +instance Show Int64 where + show (Int64 (Internal.Long' l)) = Internal.toString_ l decimal <> "l" + +derive newtype instance Eq Int64 +derive newtype instance Ord Int64 +derive newtype instance Bounded Int64 +derive newtype instance Semiring Int64 +derive newtype instance Ring Int64 +derive newtype instance CommutativeRing Int64 +derive newtype instance EuclideanRing Int64 +derive newtype instance Arbitrary Int64 -- | Creates an `Int64` from an `Int` value. fromInt :: Int -> Int64 -fromInt = Internal.signedLongFromInt +fromInt a = Int64 (Internal.signedLongFromInt a) -- | Creates an `Int64` from a `Number` value. The number must already be an -- | integer and fall within the valid range of values for the `Int64` type -- | otherwise `Nothing` is returned. fromNumber :: Number -> Maybe Int64 -fromNumber = Internal.fromNumber +fromNumber n = Int64 <$> Internal.fromNumber n -- | Creates an `Int64` from low and high bits represented as `Int`. fromLowHighBits :: Int -> Int -> Int64 -fromLowHighBits = Internal.fromLowHighBits +fromLowHighBits a b = Int64 (Internal.fromLowHighBits a b) -- | Reads an `Int64` from a `String` value. The number must parse as an integer -- | and fall within the valid range of values for the `Int64` type, otherwise -- | `Nothing` is returned. fromString :: String -> Maybe Int64 -fromString = Internal.fromString +fromString s = Int64 <$> Internal.fromString s -- | Like `fromString`, but the integer can be specified in a different base. fromStringAs :: Radix -> String -> Maybe Int64 -fromStringAs = Internal.fromStringAs +fromStringAs r s = Int64 <$> Internal.fromStringAs r s -- | Get the low (least significant) bits of an `Int64` as an `Int`. lowBits :: Int64 -> Int -lowBits = Internal.lowBits +lowBits (Int64 a) = Internal.lowBits a -- | Get the high (most significant) bits of an `Int64` as an `Int`. highBits :: Int64 -> Int -highBits = Internal.highBits +highBits (Int64 a) = Internal.highBits a -- | Creates an `Int` if the `Int64` value is within the range of `Int64`. toInt :: Int64 -> Maybe Int -toInt = Internal.toInt +toInt (Int64 a) = Internal.toInt a -- | Like `show`, but omits the `l` suffix. toString :: Int64 -> String -toString = Internal.toString +toString (Int64 a) = Internal.toString a --- | Like `toStringAs`, but the integer can be specified in a different base. +-- | Like `toString`, but the integer can be specified in a different base. toStringAs :: Radix -> Int64 -> String -toStringAs = Internal.toStringAs +toStringAs r (Int64 a) = Internal.toStringAs r a -- | Creates a `Number` value from a `Int64`. Values not within -- | `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER` will lose precision. toNumber :: Int64 -> Number -toNumber = Internal.toNumber +toNumber (Int64 a) = Internal.toNumber a -- | Returns whether a `Int64` is `Even` or `Odd`. parity :: Int64 -> Parity -parity = Internal.parity +parity (Int64 a) = Internal.parity a --- | Returns whether a `Int64` is an even number. +-- | Returns true if an even number. even :: Int64 -> Boolean -even = Internal.even +even (Int64 a) = Internal.even a --- | Returns whether a `Int64` is an odd number. +-- | Returns true if an odd number. odd :: Int64 -> Boolean -odd = Internal.odd +odd (Int64 a) = Internal.odd a -- | The `quot` function provides _truncating_ long division (see the -- | documentation for the `EuclideanRing` class). It is identical to `div` in -- | the `EuclideanRing Int` instance if the dividend is positive, but will be -- | slightly different if the dividend is negative. quot :: Int64 -> Int64 -> Int64 -quot = Internal.quot +quot (Int64 a) (Int64 b) = Int64 (Internal.quot a b) -- | The `rem` function provides the remainder after _truncating_ long -- | division (see the documentation for the `EuclideanRing` class). It is -- | identical to `mod` in the `EuclideanRing Int` instance if the dividend is -- | positive, but will be slightly different if the dividend is negative. rem :: Int64 -> Int64 -> Int64 -rem = Internal.rem +rem (Int64 a) (Int64 b) = Int64 (Internal.rem a b) --- | Converts to a `UInt64` by reading the bits as a 64 bit unsigned integer. +-- | Converts to a `UInt64` by casting the bits as a 64-bit unsigned integer. toUnsigned :: Int64 -> UInt64 -toUnsigned = Internal.signedToUnsigned +toUnsigned (Int64 a) = unsafeCoerce (Internal.signedToUnsigned a) + +-- | Converts to an `Int64` by casting the bits as a 2’s-complement 64-bit signed integer. +toSigned :: UInt64 -> Int64 +toSigned a = Int64 (Internal.unsignedToSigned (unsafeCoerce a)) -- | Bitwise AND. and :: Int64 -> Int64 -> Int64 -and = Internal.and +and (Int64 a) (Int64 b) = Int64 (Internal.and a b) infixl 10 and as .&. -- | Bitwise OR. or :: Int64 -> Int64 -> Int64 -or = Internal.or +or (Int64 a) (Int64 b) = Int64 (Internal.or a b) infixl 10 or as .|. -- | Bitwise XOR. xor :: Int64 -> Int64 -> Int64 -xor = Internal.xor +xor (Int64 a) (Int64 b) = Int64 (Internal.xor a b) infixl 10 xor as .^. -- | Bitwise shift left. shl :: Int64 -> Int64 -> Int64 -shl = Internal.shl +shl (Int64 a) (Int64 b) = Int64 (Internal.shl a b) -- | Bitwise shift right. shr :: Int64 -> Int64 -> Int64 -shr = Internal.shr +shr (Int64 a) (Int64 b) = Int64 (Internal.shr a b) -- | Bitwise zero-fill shift right. zshr :: Int64 -> Int64 -> Int64 -zshr = Internal.zshr +zshr (Int64 a) (Int64 b) = Int64 (Internal.zshr a b) -- | Bitwise NOT. complement :: Int64 -> Int64 -complement = Internal.complement +complement (Int64 a) = Int64 (Internal.complement a) diff --git a/src/Data/Int64/Internal.purs b/src/Data/Int64/Internal.purs index 2794156..dd40ffd 100644 --- a/src/Data/Int64/Internal.purs +++ b/src/Data/Int64/Internal.purs @@ -1,13 +1,11 @@ module Data.Int64.Internal - ( Int64 - , IsLittleEndian(..) + ( IsLittleEndian(..) , IsUnsigned(..) , Long - , Long' + , Long'(..) , SignProxy(..) , Signed , Signedness - , UInt64 , Unsigned , add_ , and @@ -141,14 +139,9 @@ instance infoUnsigned :: SInfo Unsigned where if high == 0 && low > 0 then Just low else Nothing +-- | Newtype wrapper for the foreign JavaScript `Long` object. newtype Long' (s :: Signedness) = Long' Long --- | Unsigned 64-bit integer. -type UInt64 = Long' Unsigned - --- | Signed two’s-complement 64-bit integer. -type Int64 = Long' Signed - instance showLong' :: Show (Long' s) where show (Long' l) = show l @@ -337,7 +330,7 @@ foreign import isWholeNumber_ :: Number -> Boolean -- FFI.purs from here --- A 64 bit two's-complement integer +-- | The foreign JavaScript `Long` object. foreign import data Long :: Type instance showLong :: Show Long where diff --git a/src/Data/UInt64.purs b/src/Data/UInt64.purs index 4040b6f..d032d2c 100644 --- a/src/Data/UInt64.purs +++ b/src/Data/UInt64.purs @@ -1,8 +1,43 @@ --- | Unsigned 64-bit integers. +-- | Unsigned 64-bit integers and operations. +-- | +-- | All of the usual arithmetic operations are supplied by typeclass +-- | instances. +-- | +-- | #### Usage +-- | +-- | ```purescript +-- | import Prelude +-- | import Data.UInt64 as UInt64 +-- | +-- | let +-- | hundred = UInt64.unsafeFromInt 100 +-- | billion = UInt64.unsafeFromInt 1000000000 +-- | ``` +-- | --- +-- | ```purescript +-- | > hundred * billion +-- | 100000000000ul +-- | ``` +-- | --- +-- | ```purescript +-- | > billion / hundred +-- | 10000000ul +-- | ``` +-- | --- +-- | ```purescript +-- | > hundred + one +-- | 101ul +-- | ``` +-- | --- +-- | ```purescript +-- | > hundred * zero +-- | 0ul +-- | ``` module Data.UInt64 - ( module R - , fromLowHighBits + ( UInt64 , fromInt + , unsafeFromInt + , fromLowHighBits , fromNumber , fromString , fromStringAs @@ -17,7 +52,6 @@ module Data.UInt64 , odd , quot , rem - , toSigned , and , (.&.) , or @@ -30,115 +64,135 @@ module Data.UInt64 , complement ) where -import Data.Int (Parity, Radix) -import Data.Int64.Internal (UInt64) as R -import Data.Int64.Internal (Int64, UInt64) +import Prelude + +import Data.Int (Parity, Radix, decimal) import Data.Int64.Internal as Internal import Data.Maybe (Maybe) +import Test.QuickCheck (class Arbitrary) + +-- | Unsigned 64-bit integer. +newtype UInt64 = UInt64 (Internal.Long' Internal.Unsigned) + +-- | The `Show` instance will suffix a lowercase ‘ul’ for “unsigned long”. +-- | (See `toString`.) +instance Show UInt64 where + show (UInt64 (Internal.Long' l)) = Internal.toString_ l decimal <> "ul" + +derive newtype instance Eq UInt64 +derive newtype instance Ord UInt64 +derive newtype instance Bounded UInt64 +derive newtype instance Semiring UInt64 +derive newtype instance Ring UInt64 +derive newtype instance CommutativeRing UInt64 +derive newtype instance EuclideanRing UInt64 +derive newtype instance Arbitrary UInt64 -- | Creates a `UInt64` from an `Int` value. fromInt :: Int -> Maybe UInt64 -fromInt = Internal.unsignedLongFromInt +fromInt a = UInt64 <$> Internal.unsignedLongFromInt a + +-- | Creates a `UInt64` from an `Int` value. +-- | +-- | If the `Int` is negative, the result is undefined. +unsafeFromInt :: Int -> UInt64 +unsafeFromInt a = UInt64 (Internal.unsafeFromInt a) -- | Creates a `UInt64` from a `Number` value. The number must already be an -- | integer and fall within the valid range of values for the `UInt64` type -- | otherwise `Nothing` is returned. fromNumber :: Number -> Maybe UInt64 -fromNumber = Internal.fromNumber +fromNumber n = UInt64 <$> Internal.fromNumber n -- | Creates a `UInt64` from low and high bits represented as `Int`. fromLowHighBits :: Int -> Int -> UInt64 -fromLowHighBits = Internal.fromLowHighBits +fromLowHighBits a b = UInt64 (Internal.fromLowHighBits a b) -- | Reads a `UInt64` from a `String` value. The number must parse as an integer -- | and fall within the valid range of values for the `UInt64` type, otherwise -- | `Nothing` is returned. fromString :: String -> Maybe UInt64 -fromString = Internal.fromString +fromString s = UInt64 <$> Internal.fromString s -- | Like `fromString`, but the integer can be specified in a different base. fromStringAs :: Radix -> String -> Maybe UInt64 -fromStringAs = Internal.fromStringAs +fromStringAs r s = UInt64 <$> Internal.fromStringAs r s -- | Get the low (least significant) 32 bits of a `UInt64` as an `Int`. lowBits :: UInt64 -> Int -lowBits = Internal.lowBits +lowBits (UInt64 a) = Internal.lowBits a -- | Get the high (most significant) 32 bits of a `UInt64` as an `Int`. highBits :: UInt64 -> Int -highBits = Internal.highBits +highBits (UInt64 a) = Internal.highBits a --- | Creates an `Int` if the `UInt64` value is within the range of `UInt64`. +-- | Creates an `Int` if the `UInt64` value is positive. toInt :: UInt64 -> Maybe Int -toInt = Internal.toInt +toInt (UInt64 a) = Internal.toInt a -- | Creates a `Number` value from a `UInt64`. Values greater than -- | `Number.MAX_SAFE_INTEGER` will lose precision. toNumber :: UInt64 -> Number -toNumber = Internal.toNumber +toNumber (UInt64 a) = Internal.toNumber a -- | Like `show`, but omits the `ul` suffix. toString :: UInt64 -> String -toString = Internal.toString +toString (UInt64 a) = Internal.toString a --- | Like `toStringAs`, but the integer can be specified in a different base. +-- | Like `toString`, but the integer can be specified in a different base. toStringAs :: Radix -> UInt64 -> String -toStringAs = Internal.toStringAs +toStringAs r (UInt64 a) = Internal.toStringAs r a -- | Returns whether a `UInt64` is `Even` or `Odd`. parity :: UInt64 -> Parity -parity = Internal.parity +parity (UInt64 a) = Internal.parity a --- | Returns whether a `UInt64` is an even number. +-- | Returns true if an even number. even :: UInt64 -> Boolean -even = Internal.even +even (UInt64 a) = Internal.even a --- | Returns whether a `UInt64` is an odd number. +-- | Returns true if an odd number. odd :: UInt64 -> Boolean -odd = Internal.odd +odd (UInt64 a) = Internal.odd a --- | For unsigned longs, `quot` is identical to `div`. +-- | `quot` is identical to `div`. quot :: UInt64 -> UInt64 -> UInt64 -quot = Internal.quot +quot (UInt64 a) (UInt64 b) = UInt64 (Internal.quot a b) --- | For unsigned longs, `quot` is identical to `mod`. +-- | `rem` is identical to `mod`. rem :: UInt64 -> UInt64 -> UInt64 -rem = Internal.rem - --- | Converts to an `Int64` by reading the bits as a 2’s-complement 64-bit signed integer. -toSigned :: UInt64 -> Int64 -toSigned = Internal.unsignedToSigned +rem (UInt64 a) (UInt64 b) = UInt64 (Internal.rem a b) -- | Bitwise AND. and :: UInt64 -> UInt64 -> UInt64 -and = Internal.and +and (UInt64 a) (UInt64 b) = UInt64 (Internal.and a b) infixl 10 and as .&. -- | Bitwise OR. or :: UInt64 -> UInt64 -> UInt64 -or = Internal.or +or (UInt64 a) (UInt64 b) = UInt64 (Internal.or a b) infixl 10 or as .|. -- | Bitwise XOR. xor :: UInt64 -> UInt64 -> UInt64 -xor = Internal.xor +xor (UInt64 a) (UInt64 b) = UInt64 (Internal.xor a b) infixl 10 xor as .^. -- | Bitwise shift left. shl :: UInt64 -> UInt64 -> UInt64 -shl = Internal.shl +shl (UInt64 a) (UInt64 b) = UInt64 (Internal.shl a b) -- | Bitwise shift right. shr :: UInt64 -> UInt64 -> UInt64 -shr = Internal.shr +shr (UInt64 a) (UInt64 b) = UInt64 (Internal.shr a b) -- | Bitwise zero-fill shift right. zshr :: UInt64 -> UInt64 -> UInt64 -zshr = Internal.zshr +zshr (UInt64 a) (UInt64 b) = UInt64 (Internal.zshr a b) -- | Bitwise NOT. complement :: UInt64 -> UInt64 -complement = Internal.complement +complement (UInt64 a) = UInt64 (Internal.complement a) diff --git a/test/Data/Long/InternalSpec.purs b/test/Data/Long/InternalSpec.purs index a4691da..810f5a5 100644 --- a/test/Data/Long/InternalSpec.purs +++ b/test/Data/Long/InternalSpec.purs @@ -6,12 +6,17 @@ import Prelude import Control.Monad.Gen (chooseInt) import Data.Int (Parity(..), Radix, binary, decimal, hexadecimal, octal, radix) -import Data.Int64.Internal (class SInfo, Int64, Long', SignProxy(..), Signed, Unsigned, UInt64) +import Data.Int64 (Int64) +import Data.Int64 as Int64 +import Data.Int64.Internal (class SInfo, Long', SignProxy(..), Signed, Unsigned) import Data.Int64.Internal as Internal import Data.Maybe (Maybe(..), isJust, isNothing) import Data.Number as Number import Data.Ord (abs) import Data.Traversable (traverse_) +import Data.UInt64 (UInt64) +import Data.UInt64 (UInt64) +import Data.UInt64 as UInt64 import Effect.Aff (Aff) import Effect.Class (liftEffect) import Test.QuickCheck (class Arbitrary, class Testable, arbitrary, quickCheck) @@ -45,9 +50,9 @@ longSpec = describe "Long" do it "should be built from high and low bits" do quickCheck' \high low -> let - l = Internal.fromLowHighBits low high :: Int64 + l = Int64.fromLowHighBits low high :: Int64 in - Internal.highBits l == high && Internal.lowBits l == low + Int64.highBits l == high && Int64.lowBits l == low it "should convert ints" $ do quickCheck' \i -> Internal.toInt (Internal.signedLongFromInt i) == Just i @@ -63,10 +68,10 @@ longSpec = describe "Long" do it "should convert to strings" $ do quickCheck' \(Radix' r) l -> - readSigned r (Internal.toStringAs r l) == Just l + readSigned r (Int64.toStringAs r l) == Just l quickCheck' \(Radix' r) l -> - readUnsigned r (Internal.toStringAs r l) == Just l + readUnsigned r (UInt64.toStringAs r l) == Just l it "should convert numbers" $ do traverse_ (checkNumber signedProxy) @@ -84,7 +89,7 @@ longSpec = describe "Long" do ] it "should reject conversion from non whole numbers" $ do - traverse_ (\n -> (Internal.fromNumber n :: Maybe Int64) `shouldSatisfy` isNothing) + traverse_ (\n -> (Int64.fromNumber n :: Maybe Int64) `shouldSatisfy` isNothing) [ 5.5 , 100.1 , 200.25 @@ -95,22 +100,22 @@ longSpec = describe "Long" do ] it "should reject conversion of numbers outside the long range" $ do - traverse_ (\n -> (Internal.fromNumber n :: Maybe Int64) `shouldSatisfy` isNothing) + traverse_ (\n -> (Int64.fromNumber n :: Maybe Int64) `shouldSatisfy` isNothing) [ -10000000000000000000.0 -- Must be big enough to store precision , 10000000000000000000.0 ] - traverse_ (\n -> (Internal.fromNumber n :: Maybe UInt64) `shouldSatisfy` isNothing) + traverse_ (\n -> (UInt64.fromNumber n :: Maybe UInt64) `shouldSatisfy` isNothing) [ -1.0 , 20000000000000000000.0 ] it "should determine odd/even" do - quickCheck' \(l :: Int64) -> (Internal.parity l == Even) == (l `mod` two == zero) - quickCheck' \(l :: UInt64) -> (Internal.parity l == Even) == (l `mod` two == zero) + quickCheck' \(l :: Int64) -> (Int64.parity l == Even) == (l `mod` (Int64.fromInt 2) == zero) + quickCheck' \(l :: UInt64) -> (UInt64.parity l == Even) == (l `mod` (UInt64.unsafeFromInt 2) == zero) it "should always have positive mods" do - quickCheck' \(l1 :: Int64) l2 -> Internal.positive $ l1 `mod` l2 + quickCheck' \(l1 :: Int64) l2 -> (_ > zero) $ l1 `mod` l2 it "should div, quot, mod, rem by 0 be 0" do traverse_ (\f -> f (Internal.signedLongFromInt 2) zero `shouldEqual` zero) @@ -178,13 +183,13 @@ fromStringSpec = describe "fromString" do readSigned hexadecimal "-8000000000000001" `shouldSatisfy` isNothing readSigned :: Radix -> String -> Maybe Int64 -readSigned = Internal.fromStringAs +readSigned = Int64.fromStringAs readUnsigned :: Radix -> String -> Maybe UInt64 -readUnsigned = Internal.fromStringAs +readUnsigned = UInt64.fromStringAs i2lS :: Int -> Int64 -i2lS = Internal.signedLongFromInt +i2lS = Int64.fromInt -- i2lU :: Int -> UInt64 -- i2lU = Internal.unsafeFromInt @@ -204,14 +209,11 @@ signedProxy = SignProxy unsignedProxy :: SignProxy Unsigned unsignedProxy = SignProxy -two :: forall s. (SInfo s) => Long' s -two = Internal.unsafeFromInt 2 - -- Helper for Longs within the Int range newtype IntInSignedLong = IntInSignedLong Int64 instance arbitraryIntInSignedLong :: Arbitrary IntInSignedLong where - arbitrary = IntInSignedLong <<< Internal.signedLongFromInt <$> arbitrary + arbitrary = IntInSignedLong <<< Int64.fromInt <$> arbitrary derive newtype instance eqIntInSignedLong :: Eq IntInSignedLong derive newtype instance semiringIntInSignedLong :: Semiring IntInSignedLong diff --git a/test/Main.purs b/test/Main.purs index 501a442..b6aa606 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -2,9 +2,13 @@ module Test.Main where import Prelude +import Data.Int64 (Int64) import Data.Int64 as Int64 import Data.Long.FFISpec (ffiSpec) import Data.Long.InternalSpec (internalSpec) +import Data.Maybe (Maybe(..)) +import Data.UInt64 (UInt64) +import Data.UInt64 as UInt64 import Effect (Effect) import Effect.Aff (launchAff_) import Test.Spec (describe, it) @@ -25,9 +29,17 @@ main = launchAff_ $ runSpec [ consoleReporter ] do shouldEqual (show hundredbillion) ("100000000000l") + shouldEqual + (Just hundredbillion) + (Int64.fromString "100000000000") shouldEqual (Int64.fromInt 0) zero shouldEqual (billion / hundred) (Int64.fromInt 10000000) shouldEqual (show $ Int64.lowBits hundredbillion) "1215752192" shouldEqual (show $ Int64.highBits hundredbillion) "23" + shouldEqual true $ case (one :: Int64) of + x | x == Int64.fromInt 1 -> true + _ -> false + shouldEqual (show (one :: UInt64)) "1ul" + shouldEqual (Just 2) (UInt64.toInt =<< UInt64.fromInt 2)