int-cast-0.2.0.0: Checked conversions between integral types

Copyright© 2014-2018 Herbert Valerio Riedel
LicenseBSD-style (see the LICENSE file)
MaintainerHerbert Valerio Riedel <hvr@gnu.org>
Stabilityexperimental
PortabilityGHC ≥ 7.8
Safe HaskellSafe
LanguageHaskell2010

Data.IntCast

Contents

Description

This module provides for statically or dynamically checked conversions between Integral types.

Synopsis

Conversion functions

statically checked

In the table below each cell denotes which of the three intCast, intCastIso and intCastEq conversion operations are allowed (i.e. by the type-checker). The rows represent the domain a while the columns represent the codomain b of the a->b-typed conversion functions.

Natural Word32 Word64 Int
Word intCast intCast & intCastEq & intCastIso intCastIso
Word16 intCast intCast intCast intCast
Int64 intCastIso intCast & intCastEq & intCastIso
Int8 intCast

Note: The table above assumes a 64-bit platform (i.e. where finiteBitSize (0 :: Word) == 64).

intCast :: (Integral a, Integral b, IsIntSubType a b ~ True) => a -> b Source #

Statically checked integer conversion which satisfies the property

Note: This is just a type-restricted alias of fromIntegral and should therefore lead to the same compiled code as if fromIntegral had been used instead of intCast.

intCastIso :: (Integral a, Integral b, IsIntTypeIso a b ~ True) => a -> b Source #

Statically checked integer conversion which satisfies the properties

Note: This is just a type-restricted alias of fromIntegral and should therefore lead to the same compiled code as if fromIntegral had been used instead of intCastIso.

intCastEq :: (Integral a, Integral b, IsIntTypeEq a b ~ True) => a -> b Source #

Version of intCast restricted to casts between types with same value domain.

intCastEq is the most constrained of the three conversions: The existence of a intCastEq conversion implies the existence of the other two, i.e. intCastIso and intCast.

Note: This is just a type-restricted alias of fromIntegral and should therefore lead to the same compiled code as if fromIntegral had been used instead of intCastIso.

dynamically checked

intCastMaybe :: (Integral a, Integral b, Bits a, Bits b) => a -> Maybe b Source #

Run-time-checked integer conversion

This is an optimized version of the following generic code below

intCastMaybeRef :: (Integral a, Integral b) => a -> Maybe b
intCastMaybeRef x
  | toInteger x == toInteger y = Just y
  | otherwise                  = Nothing
  where
    y = fromIntegral x

The code above is rather inefficient as it needs to go via the Integer type. The function intCastMaybe, however, is marked INLINEABLE and if both integral types are statically known, GHC will be able optimize the code signficantly (for -O1 and better).

For instance (as of GHC 7.8.1) the following definitions

w16_to_i32 = intCastMaybe :: Word16 -> Maybe Int32

i16_to_w16 = intCastMaybe :: Int16 -> Maybe Word16

are translated into the following (simplified) GHC Core language

w16_to_i32 = \x -> Just (case x of _ { W16# x# -> I32# (word2Int# x#) })

i16_to_w16 = \x -> case eta of _
  { I16# b1 -> case tagToEnum# (<=# 0 b1) of _
      { False -> Nothing
      ; True -> Just (W16# (narrow16Word# (int2Word# b1)))
      }
  }

Note: Starting with base-4.8, this function has been added to Data.Bits under the name toIntegralSized.

Registering new integer types

type family IntBaseType a :: IntBaseTypeK Source #

The (open) type family IntBaseType encodes type-level information about the value range of an integral type.

This module also provides type family instances for the standard Haskell 2010 integral types (including Foreign.C.Types) as well as the Natural type.

Here's a simple example for registering a custom type with the Data.IntCast facilities:

-- user-implemented unsigned 4-bit integer
data Nibble = …

-- declare meta-information
type instance IntBaseType Nibble = FixedWordTag 4

-- user-implemented signed 7-bit integer
data MyInt7 = …

-- declare meta-information
type instance IntBaseType MyInt7 = FixedIntTag 7

The type-level predicate IsIntSubType provides a partial ordering based on the types above. See also intCast.

Instances
type IntBaseType Int Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Int8 Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Int16 Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Int32 Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Int64 Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Integer Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Natural Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Word Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Word8 Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Word16 Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Word32 Source # 
Instance details

Defined in Data.IntCast

type IntBaseType Word64 Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CChar Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CSChar Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CUChar Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CShort Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CUShort Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CInt Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CUInt Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CLong Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CULong Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CLLong Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CULLong Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CPtrdiff Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CSize Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CSigAtomic Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CIntPtr Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CUIntPtr Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CIntMax Source # 
Instance details

Defined in Data.IntCast

type IntBaseType CUIntMax Source # 
Instance details

Defined in Data.IntCast

data IntBaseTypeK Source #

(Kind) Meta-information about integral types.

If also a Bits instance is defined, the type-level information provided by IntBaseType ought to match the meta-information that is conveyed by the Bits class' isSigned and bitSizeMaybe methods.

Constructors

FixedIntTag Nat

fixed-width \(n\)-bit integers with value range \( \left[ -2^{n-1}, 2^{n-1}-1 \right] \).

FixedWordTag Nat

fixed-width \(n\)-bit integers with value range \( \left[ 0, 2^{n} \right] \).

BigIntTag

integers with value range \( \left] -\infty, +\infty \right[ \).

BigWordTag

naturals with value range \( \left[ 0, +\infty \right[ \).

Type-level predicates

The following type-level predicates are used by intCast, intCastIso, and intCastEq respectively.

type family IsIntBaseSubType a b :: Bool where ... Source #

Closed type family providing the partial order of (improper) subtype-relations

IsIntSubType provides a more convenient entry point.

type family IsIntBaseTypeIso a b :: Bool where ... Source #

Closed type family representing an equality-relation on bit-width

This is a superset of the IsIntBaseTypeEq relation, as it ignores the signedness of fixed-size integers (i.e. Int32 is considered equal to Word32).

IsIntTypeIso provides a more convenient entry point.

type family IsIntBaseTypeEq (a :: IntBaseTypeK) (b :: IntBaseTypeK) :: Bool where ... Source #

Closed type family representing an equality-relation on the integer base-type.

IsIntBaseTypeEq provides a more convenient entry point.

Equations

IsIntBaseTypeEq a a = True 
IsIntBaseTypeEq a b = False