{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Data.TypeNums.Ints
(
TInt(..)
, KnownInt
, intVal
, intVal'
, SomeInt(..)
, someIntVal
) where
import Data.Bifunctor (first)
import Data.Proxy (Proxy (..))
import GHC.Exts (Proxy#, proxy#)
import GHC.TypeLits (KnownNat, Nat, natVal')
import Unsafe.Coerce (unsafeCoerce)
newtype SInt (n :: k) =
SInt Integer
data TInt
= Pos Nat
| Neg Nat
class KnownInt (n :: k) where
intSing :: SInt n
instance forall n. KnownNat n => KnownInt n where
intSing = SInt $! natVal' (proxy# @Nat @n)
instance forall n. KnownNat n => KnownInt ('Pos n) where
intSing = SInt $! natVal' (proxy# @Nat @n)
instance forall n. KnownNat n => KnownInt ('Neg n) where
intSing = SInt $! negate (natVal' (proxy# @Nat @n))
intVal ::
forall n proxy. KnownInt n
=> proxy n
-> Integer
intVal _ =
case intSing :: SInt n of
SInt x -> x
intVal' ::
forall n. KnownInt n
=> Proxy# n
-> Integer
intVal' _ =
case intSing :: SInt n of
SInt x -> x
data SomeInt =
forall n. KnownInt n =>
SomeInt (Proxy n)
instance Eq SomeInt where
SomeInt x == SomeInt y = intVal x == intVal y
instance Ord SomeInt where
compare (SomeInt x) (SomeInt y) = compare (intVal x) (intVal y)
instance Show SomeInt where
showsPrec p (SomeInt x) = showsPrec p (intVal x)
instance Read SomeInt where
readsPrec p xs = first someIntVal <$> readsPrec p xs
data SomeIntWithDict =
forall n. SomeIntWithDict (SInt n)
(Proxy n)
someIntVal :: Integer -> SomeInt
someIntVal x = unsafeCoerce $ SomeIntWithDict (SInt x) Proxy