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.
:: a typeCtrl KGHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05
Moduleint-cast-0.2.0.0Haskell2010
This module provides for statically or dynamically checked conversions between Integral types.
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.
& & | ||||
& & | ||||
Note: The table above assumes a 64-bit platform (i.e. where finiteBitSize (0 :: Word) == 64).
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.
Statically checked integer conversion which satisfies the properties
∀β . intCastIso (intCastIso a ∷ β) == atoInteger (intCastIso a) == toInteger b (if toInteger a == toInteger b)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.
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.
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 xThe 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 Word16are 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.
For intCastMaybe you need to provide type-class instances of Bits (and Integral).
For intCast, intCastIso, and intCastEq simply declare instances for the IntBaseType type-family (as well as type-class instances of Integral) as described below.
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.
type IntBaseType Integer = 'BigIntTagDefined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Natural = 'BigWordTagDefined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CChar = IntBaseType Int8Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CInt = IntBaseType Int32Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CIntMax = IntBaseType Int64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CIntPtr = IntBaseType Int64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CLLong = IntBaseType Int64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CLong = IntBaseType Int64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CPtrdiff = IntBaseType Int64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CSChar = IntBaseType Int8Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CShort = IntBaseType Int16Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CSigAtomic = IntBaseType Int32Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CSize = IntBaseType Word64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CUChar = IntBaseType Word8Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CUInt = IntBaseType Word32Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CUIntMax = IntBaseType Word64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CUIntPtr = IntBaseType Word64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CULLong = IntBaseType Word64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CULong = IntBaseType Word64Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType CUShort = IntBaseType Word16Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Int16 = 'FixedIntTag 16
Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Int32 = 'FixedIntTag 32
Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Int64 = 'FixedIntTag 64
Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Int8 = 'FixedIntTag 8
Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Word16 = 'FixedWordTag 16
Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Word32 = 'FixedWordTag 32
Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Word64 = 'FixedWordTag 64
Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Word8 = 'FixedWordTag 8
Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Int = 'FixedIntTag 64
Defined in int-cast-0.2.0.0 · Data.IntCasttype IntBaseType Word = 'FixedWordTag 64
Defined in int-cast-0.2.0.0 · Data.IntCast(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.
FixedIntTag Natfixed-width n-bit integers with value range \left[ -2^{n-1}, 2^{n-1}-1 \right] .
FixedWordTag Natfixed-width n-bit integers with value range \left[ 0, 2^{n} \right] .
BigIntTagintegers with value range \left] -\infty, +\infty \right[ .
BigWordTagnaturals with value range \left[ 0, +\infty \right[ .
The following type-level predicates are used by intCast, intCastIso, and intCastEq respectively.
Closed type family providing the partial order of (improper) subtype-relations
IsIntSubType provides a more convenient entry point.
IsIntBaseSubType a a = 'TrueIsIntBaseSubType a 'BigIntTag = 'TrueIsIntBaseSubType ('FixedWordTag a) 'BigWordTag = 'TrueIsIntBaseSubType ('FixedIntTag a) ('FixedIntTag b) = a <=? bIsIntBaseSubType ('FixedWordTag a) ('FixedWordTag b) = a <=? bIsIntBaseSubType ('FixedWordTag a) ('FixedIntTag b) = (a + 1
) <=? bIsIntBaseSubType a b = 'FalseClosed 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.
IsIntBaseTypeIso a a = 'TrueIsIntBaseTypeIso ('FixedIntTag n) ('FixedWordTag n) = 'TrueIsIntBaseTypeIso ('FixedWordTag n) ('FixedIntTag n) = 'TrueIsIntBaseTypeIso a b = 'FalseClosed type family representing an equality-relation on the integer base-type.
IsIntBaseTypeEq provides a more convenient entry point.
IsIntBaseTypeEq a a = 'TrueIsIntBaseTypeEq a b = 'False