| 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 ∷ β) == a
- toInteger(- intCastIsoa) ==- toIntegerb (if- toIntegera ==- 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 |