-- | Provides the 'FromInteger' typeclass.
--
-- @since 0.1
module Numeric.Literal.Integer
  ( FromInteger (..),
  )
where

import Data.Complex (Complex)
import Data.Int (Int16, Int32, Int64, Int8)
import Data.Kind (Constraint, Type)
import Data.Ratio (Ratio)
import Data.Word (Word16, Word32, Word64, Word8)
import GHC.Natural (Natural)
import GHC.Stack.Types (HasCallStack)

{- HLINT ignore FromInteger "Redundant bracket" -}

-- | Replaces base's @fromInteger@ functionality for when we do not have a
-- 'Num' instance.
--
-- @
-- 1_000 :: Num a => a
--
-- -- becomes
--
-- afromInteger 1_000 :: FromInteger a => a
-- @
--
-- Note that @fromInteger@'s deficiencies are inherited e.g. 'Natural' is
-- partial, bounded types have over/underflow issues.
--
-- @since 0.1
type FromInteger :: Type -> Constraint
class FromInteger a where
  -- | @since 0.1
  afromInteger :: (HasCallStack) => Integer -> a

-- | @since 0.1
instance FromInteger Double where
  afromInteger :: HasCallStack => Integer -> Double
afromInteger = Integer -> Double
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Float where
  afromInteger :: HasCallStack => Integer -> Float
afromInteger = Integer -> Float
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Int where
  afromInteger :: HasCallStack => Integer -> Int
afromInteger = Integer -> Int
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Int8 where
  afromInteger :: HasCallStack => Integer -> Int8
afromInteger = Integer -> Int8
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Int16 where
  afromInteger :: HasCallStack => Integer -> Int16
afromInteger = Integer -> Int16
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Int32 where
  afromInteger :: HasCallStack => Integer -> Int32
afromInteger = Integer -> Int32
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Int64 where
  afromInteger :: HasCallStack => Integer -> Int64
afromInteger = Integer -> Int64
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Integer where
  afromInteger :: HasCallStack => Integer -> Integer
afromInteger = Integer -> Integer
forall a. a -> a
id
  {-# INLINE afromInteger #-}

-- | __WARNING: Partial__
--
-- @since 0.1
instance FromInteger Natural where
  afromInteger :: HasCallStack => Integer -> Natural
afromInteger = Integer -> Natural
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Word where
  afromInteger :: HasCallStack => Integer -> Word
afromInteger = Integer -> Word
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Word8 where
  afromInteger :: HasCallStack => Integer -> Word8
afromInteger = Integer -> Word8
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Word16 where
  afromInteger :: HasCallStack => Integer -> Word16
afromInteger = Integer -> Word16
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Word32 where
  afromInteger :: HasCallStack => Integer -> Word32
afromInteger = Integer -> Word32
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger Word64 where
  afromInteger :: HasCallStack => Integer -> Word64
afromInteger = Integer -> Word64
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance FromInteger (Ratio Integer) where
  afromInteger :: HasCallStack => Integer -> Ratio Integer
afromInteger = Integer -> Ratio Integer
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | __WARNING: Partial__
--
-- @since 0.1
instance FromInteger (Ratio Natural) where
  afromInteger :: HasCallStack => Integer -> Ratio Natural
afromInteger = Integer -> Ratio Natural
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}

-- | @since 0.1
instance (RealFloat a) => FromInteger (Complex a) where
  afromInteger :: HasCallStack => Integer -> Complex a
afromInteger = Integer -> Complex a
forall a. Num a => Integer -> a
fromInteger
  {-# INLINE afromInteger #-}