| Copyright | © 2014 Herbert Valerio Riedel |
|---|---|
| License | BSD-style (see the LICENSE file) |
| Maintainer | Herbert Valerio Riedel <hvr@gnu.org> |
| Stability | experimental |
| Portability | GHC ≥ 7.8 |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.IntCast
Contents
Description
This module provides for statically or dynamically checked
conversions between Integral types.
- intCast :: (Integral a, Integral b, IsIntSubType a b ~ True) => a -> b
- intCastIso :: (Integral a, Integral b, IsIntTypeIso a b ~ True) => a -> b
- intCastEq :: (Integral a, Integral b, IsIntTypeEq a b ~ True) => a -> b
- intCastMaybe :: (Integral a, Integral b, Bits a, Bits b) => a -> Maybe b
- type family IntBaseType a :: IntBaseTypeK
- data IntBaseTypeK
- type IsIntSubType a b = IsIntBaseSubType (IntBaseType a) (IntBaseType b)
- type family IsIntBaseSubType a b :: Bool
- type IsIntTypeIso a b = IsIntBaseTypeIso (IntBaseType a) (IntBaseType b)
- type family IsIntBaseTypeIso a b :: Bool
- type IsIntTypeEq a b = IsIntBaseTypeEq (IntBaseType a) (IntBaseType b)
- type family IsIntBaseTypeEq a b :: Bool
Conversion functions
statically checked
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
∀β .
intCastIso(intCastIsoa ∷ β) == atoInteger(intCastIsoa) ==toIntegerb (iftoIntegera ==toIntegerb)
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.
intCastEq :: (Integral a, Integral b, IsIntTypeEq a b ~ True) => a -> b Source
Version of intCast restricted to casts between types with same value domain.
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 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 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)))
}
}Registering new integer types
- For
intCastMaybeyou need to provide type-class instances ofBits(andIntegral). - For
intCast,intCastIso, andintCastEqsimply declare instances for theIntBaseTypetype-family (as well as type-class instances ofIntegral) as described below.
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 instanceIntBaseTypeMyWord7 =FixedIntTag4 -- user-implemented signed 7-bit integer data MyInt7 = … -- declare meta-information type instanceIntBaseTypeMyWord7 =FixedIntTag7
The type-level predicate IsIntSubType provides a partial
ordering based on the types above. See also intCast.
Instances
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 [-2ⁿ⁻¹, 2ⁿ⁻¹-1]. |
| FixedWordTag Nat | fixed-width n-bit integers with value range [0, 2ⁿ-1]. |
| BigIntTag | integers with value range ]-∞,+∞[. |
| BigWordTag | naturals with value range [0,+∞[. |
Instances
| type (==) IntBaseTypeK a b = IsIntBaseTypeEq a b |
Type-level predicates
The following type-level predicates are used by intCast,
intCastIso, and intCastEq respectively.
type IsIntSubType a b = IsIntBaseSubType (IntBaseType a) (IntBaseType b) Source
type family IsIntBaseSubType a b :: Bool Source
Equations
| IsIntBaseSubType a a = True | |
| IsIntBaseSubType a BigIntTag = True | |
| IsIntBaseSubType (FixedWordTag a) BigWordTag = True | |
| IsIntBaseSubType (FixedIntTag a) (FixedIntTag b) = a <=? b | |
| IsIntBaseSubType (FixedWordTag a) (FixedWordTag b) = a <=? b | |
| IsIntBaseSubType (FixedWordTag a) (FixedIntTag b) = (a + 1) <=? b | |
| IsIntBaseSubType a b = False |
type IsIntTypeIso a b = IsIntBaseTypeIso (IntBaseType a) (IntBaseType b) Source
type family IsIntBaseTypeIso a b :: Bool Source
Equations
| IsIntBaseTypeIso a a = True | |
| IsIntBaseTypeIso (FixedIntTag n) (FixedWordTag n) = True | |
| IsIntBaseTypeIso (FixedWordTag n) (FixedIntTag n) = True | |
| IsIntBaseTypeIso a b = False |
type IsIntTypeEq a b = IsIntBaseTypeEq (IntBaseType a) (IntBaseType b) Source
type family IsIntBaseTypeEq a b :: Bool Source
Equations
| IsIntBaseTypeEq a a = True | |
| IsIntBaseTypeEq a b = False |