--------------------------------------------------------------------------------
-- Copyright © 2011 National Institute of Aerospace / Galois, Inc.
--------------------------------------------------------------------------------

{-# LANGUAGE Safe #-}
{-# LANGUAGE MultiParamTypeClasses #-}

-- | Type-safe casting operators.
module Copilot.Language.Operators.Cast
  ( cast, unsafeCast, Cast, UnsafeCast ) where

import qualified Copilot.Core.Operators as C
import Copilot.Core.Type
import Copilot.Language.Stream

import Data.Int
import Data.Word

--------------------------------------------------------------------------------

-- | Class to capture casting between types for which it can be performed
-- safely.
class Cast a b where
  -- | Perform a safe cast from @Stream a@ to @Stream b@.
  cast :: (Typed a, Typed b) => Stream a -> Stream b

-- | Class to capture casting between types for which casting may be unsafe
-- and/or result in a loss of precision or information.
class UnsafeCast a b where
  -- | Perform an unsafe cast from @Stream a@ to @Stream b@.
  unsafeCast :: (Typed a, Typed b) => Stream a -> Stream b

--------------------------------------------------------------------------------

-- | Cast a boolean stream to a stream of numbers, producing 1 if the
-- value at a point in time is 'True', and 0 otherwise.
castBool :: (Eq a, Num a, Typed a) => Stream Bool -> Stream a
castBool :: Stream Bool -> Stream a
castBool (Const Bool
bool) = a -> Stream a
forall a. Typed a => a -> Stream a
Const (a -> Stream a) -> a -> Stream a
forall a b. (a -> b) -> a -> b
$ if Bool
bool then a
1 else a
0
castBool Stream Bool
x            = Op3 Bool a a a -> Stream Bool -> Stream a -> Stream a -> Stream a
forall a b c d.
(Typed a, Typed b, Typed c, Typed d) =>
Op3 a b c d -> Stream a -> Stream b -> Stream c -> Stream d
Op3 (Type a -> Op3 Bool a a a
forall b. Type b -> Op3 Bool b b b
C.Mux Type a
forall a. Typed a => Type a
typeOf) Stream Bool
x Stream a
1 Stream a
0

--------------------------------------------------------------------------------

-- | Identity casting.
instance Cast Bool Bool where
  cast :: Stream Bool -> Stream Bool
cast = Stream Bool -> Stream Bool
forall a. a -> a
id

-- | Cast a boolean stream to a stream of numbers, producing 1 if the
-- value at a point in time is 'True', and 0 otherwise.
instance Cast Bool Word8 where
  cast :: Stream Bool -> Stream Word8
cast = Stream Bool -> Stream Word8
forall a. (Eq a, Num a, Typed a) => Stream Bool -> Stream a
castBool

-- | Cast a boolean stream to a stream of numbers, producing 1 if the
-- value at a point in time is 'True', and 0 otherwise.
instance Cast Bool Word16 where
  cast :: Stream Bool -> Stream Word16
cast = Stream Bool -> Stream Word16
forall a. (Eq a, Num a, Typed a) => Stream Bool -> Stream a
castBool

-- | Cast a boolean stream to a stream of numbers, producing 1 if the
-- value at a point in time is 'True', and 0 otherwise.
instance Cast Bool Word32 where
  cast :: Stream Bool -> Stream Word32
cast = Stream Bool -> Stream Word32
forall a. (Eq a, Num a, Typed a) => Stream Bool -> Stream a
castBool

-- | Cast a boolean stream to a stream of numbers, producing 1 if the
-- value at a point in time is 'True', and 0 otherwise.
instance Cast Bool Word64 where
  cast :: Stream Bool -> Stream Word64
cast = Stream Bool -> Stream Word64
forall a. (Eq a, Num a, Typed a) => Stream Bool -> Stream a
castBool

-- | Cast a boolean stream to a stream of numbers, producing 1 if the
-- value at a point in time is 'True', and 0 otherwise.
instance Cast Bool Int8 where
  cast :: Stream Bool -> Stream Int8
cast = Stream Bool -> Stream Int8
forall a. (Eq a, Num a, Typed a) => Stream Bool -> Stream a
castBool

-- | Cast a boolean stream to a stream of numbers, producing 1 if the
-- value at a point in time is 'True', and 0 otherwise.
instance Cast Bool Int16 where
  cast :: Stream Bool -> Stream Int16
cast = Stream Bool -> Stream Int16
forall a. (Eq a, Num a, Typed a) => Stream Bool -> Stream a
castBool

-- | Cast a boolean stream to a stream of numbers, producing 1 if the
-- value at a point in time is 'True', and 0 otherwise.
instance Cast Bool Int32 where
  cast :: Stream Bool -> Stream Int32
cast = Stream Bool -> Stream Int32
forall a. (Eq a, Num a, Typed a) => Stream Bool -> Stream a
castBool

-- | Cast a boolean stream to a stream of numbers, producing 1 if the
-- value at a point in time is 'True', and 0 otherwise.
instance Cast Bool Int64 where
  cast :: Stream Bool -> Stream Int64
cast = Stream Bool -> Stream Int64
forall a. (Eq a, Num a, Typed a) => Stream Bool -> Stream a
castBool

--------------------------------------------------------------------------------

-- | Cast a stream carrying numbers to an integral using 'fromIntegral'.
castIntegral :: (Integral a, Typed a, Num b, Typed b) => Stream a -> Stream b
castIntegral :: Stream a -> Stream b
castIntegral (Const a
x) = b -> Stream b
forall a. Typed a => a -> Stream a
Const (a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
x)
castIntegral Stream a
x         = Op1 a b -> Stream a -> Stream b
forall a b. (Typed a, Typed b) => Op1 a b -> Stream a -> Stream b
Op1 (Type a -> Type b -> Op1 a b
forall a b. (Integral a, Num b) => Type a -> Type b -> Op1 a b
C.Cast Type a
forall a. Typed a => Type a
typeOf Type b
forall a. Typed a => Type a
typeOf) Stream a
x

--------------------------------------------------------------------------------

-- | Identity casting.
instance Cast Word8 Word8 where
  cast :: Stream Word8 -> Stream Word8
cast = Stream Word8 -> Stream Word8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word8 Word16 where
  cast :: Stream Word8 -> Stream Word16
cast = Stream Word8 -> Stream Word16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word8 Word32 where
  cast :: Stream Word8 -> Stream Word32
cast = Stream Word8 -> Stream Word32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word8 Word64 where
  cast :: Stream Word8 -> Stream Word64
cast = Stream Word8 -> Stream Word64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word8 Int16 where
  cast :: Stream Word8 -> Stream Int16
cast = Stream Word8 -> Stream Int16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word8 Int32 where
  cast :: Stream Word8 -> Stream Int32
cast = Stream Word8 -> Stream Int32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word8 Int64 where
  cast :: Stream Word8 -> Stream Int64
cast = Stream Word8 -> Stream Int64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

--------------------------------------------------------------------------------

-- | Identity casting.
instance Cast Word16 Word16 where
  cast :: Stream Word16 -> Stream Word16
cast = Stream Word16 -> Stream Word16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word16 Word32 where
  cast :: Stream Word16 -> Stream Word32
cast = Stream Word16 -> Stream Word32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word16 Word64 where
  cast :: Stream Word16 -> Stream Word64
cast = Stream Word16 -> Stream Word64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word16 Int32 where
  cast :: Stream Word16 -> Stream Int32
cast = Stream Word16 -> Stream Int32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word16 Int64 where
  cast :: Stream Word16 -> Stream Int64
cast = Stream Word16 -> Stream Int64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

--------------------------------------------------------------------------------

-- | Identity casting.
instance Cast Word32 Word32 where
  cast :: Stream Word32 -> Stream Word32
cast = Stream Word32 -> Stream Word32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word32 Word64 where
  cast :: Stream Word32 -> Stream Word64
cast = Stream Word32 -> Stream Word64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Word32 Int64 where
  cast :: Stream Word32 -> Stream Int64
cast = Stream Word32 -> Stream Int64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

--------------------------------------------------------------------------------

-- | Identity casting.
instance Cast Word64 Word64 where
  cast :: Stream Word64 -> Stream Word64
cast = Stream Word64 -> Stream Word64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

--------------------------------------------------------------------------------

-- | Identity casting.
instance Cast Int8 Int8 where
  cast :: Stream Int8 -> Stream Int8
cast = Stream Int8 -> Stream Int8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Int8 Int16 where
  cast :: Stream Int8 -> Stream Int16
cast = Stream Int8 -> Stream Int16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Int8 Int32 where
  cast :: Stream Int8 -> Stream Int32
cast = Stream Int8 -> Stream Int32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Int8 Int64 where
  cast :: Stream Int8 -> Stream Int64
cast = Stream Int8 -> Stream Int64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

--------------------------------------------------------------------------------

-- | Identity casting.
instance Cast Int16 Int16 where
  cast :: Stream Int16 -> Stream Int16
cast = Stream Int16 -> Stream Int16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Int16 Int32 where
  cast :: Stream Int16 -> Stream Int32
cast = Stream Int16 -> Stream Int32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Int16 Int64 where
  cast :: Stream Int16 -> Stream Int64
cast = Stream Int16 -> Stream Int64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

--------------------------------------------------------------------------------

-- | Identity casting.
instance Cast Int32 Int32 where
  cast :: Stream Int32 -> Stream Int32
cast = Stream Int32 -> Stream Int32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast number to bigger type.
instance Cast Int32 Int64 where
  cast :: Stream Int32 -> Stream Int64
cast = Stream Int32 -> Stream Int64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

--------------------------------------------------------------------------------

-- | Identity casting.
instance Cast Int64 Int64 where
  cast :: Stream Int64 -> Stream Int64
cast = Stream Int64 -> Stream Int64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Word64 Word32 where
  unsafeCast :: Stream Word64 -> Stream Word32
unsafeCast = Stream Word64 -> Stream Word32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Word64 Word16 where
  unsafeCast :: Stream Word64 -> Stream Word16
unsafeCast = Stream Word64 -> Stream Word16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Word64 Word8 where
  unsafeCast :: Stream Word64 -> Stream Word8
unsafeCast = Stream Word64 -> Stream Word8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Word32 Word16 where
  unsafeCast :: Stream Word32 -> Stream Word16
unsafeCast = Stream Word32 -> Stream Word16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Word32 Word8 where
  unsafeCast :: Stream Word32 -> Stream Word8
unsafeCast = Stream Word32 -> Stream Word8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Word16 Word8 where
  unsafeCast :: Stream Word16 -> Stream Word8
unsafeCast = Stream Word16 -> Stream Word8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Int64 Int32 where
  unsafeCast :: Stream Int64 -> Stream Int32
unsafeCast = Stream Int64 -> Stream Int32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Int64 Int16 where
  unsafeCast :: Stream Int64 -> Stream Int16
unsafeCast = Stream Int64 -> Stream Int16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Int64 Int8 where
  unsafeCast :: Stream Int64 -> Stream Int8
unsafeCast = Stream Int64 -> Stream Int8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Int32 Int16 where
  unsafeCast :: Stream Int32 -> Stream Int16
unsafeCast = Stream Int32 -> Stream Int16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Int32 Int8 where
  unsafeCast :: Stream Int32 -> Stream Int8
unsafeCast = Stream Int32 -> Stream Int8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe downcasting to smaller sizes.
instance UnsafeCast Int16 Int8 where
  unsafeCast :: Stream Int16 -> Stream Int8
unsafeCast = Stream Int16 -> Stream Int8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe signed integer promotion to floating point values.
instance UnsafeCast Int64 Float where
  unsafeCast :: Stream Int64 -> Stream Float
unsafeCast = Stream Int64 -> Stream Float
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe signed integer promotion to floating point values.
instance UnsafeCast Int32 Float where
  unsafeCast :: Stream Int32 -> Stream Float
unsafeCast = Stream Int32 -> Stream Float
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe signed integer promotion to floating point values.
instance UnsafeCast Int16 Float where
  unsafeCast :: Stream Int16 -> Stream Float
unsafeCast = Stream Int16 -> Stream Float
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe signed integer promotion to floating point values.
instance UnsafeCast Int8 Float where
  unsafeCast :: Stream Int8 -> Stream Float
unsafeCast = Stream Int8 -> Stream Float
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe signed integer promotion to floating point values.
instance UnsafeCast Int64 Double where
  unsafeCast :: Stream Int64 -> Stream Double
unsafeCast = Stream Int64 -> Stream Double
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe signed integer promotion to floating point values.
instance UnsafeCast Int32 Double where
  unsafeCast :: Stream Int32 -> Stream Double
unsafeCast = Stream Int32 -> Stream Double
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe signed integer promotion to floating point values.
instance UnsafeCast Int16 Double where
  unsafeCast :: Stream Int16 -> Stream Double
unsafeCast = Stream Int16 -> Stream Double
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe signed integer promotion to floating point values.
instance UnsafeCast Int8 Double where
  unsafeCast :: Stream Int8 -> Stream Double
unsafeCast = Stream Int8 -> Stream Double
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe unsigned integer promotion to floating point values.
instance UnsafeCast Word64 Float where
  unsafeCast :: Stream Word64 -> Stream Float
unsafeCast = Stream Word64 -> Stream Float
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe unsigned integer promotion to floating point values.
instance UnsafeCast Word32 Float where
  unsafeCast :: Stream Word32 -> Stream Float
unsafeCast = Stream Word32 -> Stream Float
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe unsigned integer promotion to floating point values.
instance UnsafeCast Word16 Float where
  unsafeCast :: Stream Word16 -> Stream Float
unsafeCast = Stream Word16 -> Stream Float
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe unsigned integer promotion to floating point values.
instance UnsafeCast Word8 Float where
  unsafeCast :: Stream Word8 -> Stream Float
unsafeCast = Stream Word8 -> Stream Float
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe unsigned integer promotion to floating point values.
instance UnsafeCast Word64 Double where
  unsafeCast :: Stream Word64 -> Stream Double
unsafeCast = Stream Word64 -> Stream Double
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe unsigned integer promotion to floating point values.
instance UnsafeCast Word32 Double where
  unsafeCast :: Stream Word32 -> Stream Double
unsafeCast = Stream Word32 -> Stream Double
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe unsigned integer promotion to floating point values.
instance UnsafeCast Word16 Double where
  unsafeCast :: Stream Word16 -> Stream Double
unsafeCast = Stream Word16 -> Stream Double
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Unsafe unsigned integer promotion to floating point values.
instance UnsafeCast Word8 Double where
  unsafeCast :: Stream Word8 -> Stream Double
unsafeCast = Stream Word8 -> Stream Double
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast from unsigned numbers to signed numbers.
instance UnsafeCast Word64 Int64 where
  unsafeCast :: Stream Word64 -> Stream Int64
unsafeCast = Stream Word64 -> Stream Int64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast from unsigned numbers to signed numbers.
instance UnsafeCast Word32 Int32 where
  unsafeCast :: Stream Word32 -> Stream Int32
unsafeCast = Stream Word32 -> Stream Int32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast from unsigned numbers to signed numbers.
instance UnsafeCast Word16 Int16 where
  unsafeCast :: Stream Word16 -> Stream Int16
unsafeCast = Stream Word16 -> Stream Int16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Cast from unsigned numbers to signed numbers.
instance UnsafeCast Word8 Int8 where
  unsafeCast :: Stream Word8 -> Stream Int8
unsafeCast = Stream Word8 -> Stream Int8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Signed to unsigned casting.
instance UnsafeCast Int64 Word64 where
  unsafeCast :: Stream Int64 -> Stream Word64
unsafeCast = Stream Int64 -> Stream Word64
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Signed to unsigned casting.
instance UnsafeCast Int32 Word32 where
  unsafeCast :: Stream Int32 -> Stream Word32
unsafeCast = Stream Int32 -> Stream Word32
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Signed to unsigned casting.
instance UnsafeCast Int16 Word16 where
  unsafeCast :: Stream Int16 -> Stream Word16
unsafeCast = Stream Int16 -> Stream Word16
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral

-- | Signed to unsigned casting.
instance UnsafeCast Int8 Word8 where
  unsafeCast :: Stream Int8 -> Stream Word8
unsafeCast = Stream Int8 -> Stream Word8
forall a b.
(Integral a, Typed a, Num b, Typed b) =>
Stream a -> Stream b
castIntegral