{-# 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 :: Nat). KnownNat n => KnownInt n where
intSing :: SInt n
intSing = Integer -> SInt n
forall k (n :: k). Integer -> SInt n
SInt (Integer -> SInt n) -> Integer -> SInt n
forall a b. (a -> b) -> a -> b
$! Proxy# n -> Integer
forall (n :: Nat). KnownNat n => Proxy# n -> Integer
natVal' (Proxy# n
forall k (a :: k). Proxy# a
proxy# :: Proxy# n)
instance forall (n :: Nat). KnownNat n => KnownInt ('Pos n) where
intSing :: SInt ('Pos n)
intSing = Integer -> SInt ('Pos n)
forall k (n :: k). Integer -> SInt n
SInt (Integer -> SInt ('Pos n)) -> Integer -> SInt ('Pos n)
forall a b. (a -> b) -> a -> b
$! Proxy# n -> Integer
forall (n :: Nat). KnownNat n => Proxy# n -> Integer
natVal' (Proxy# n
forall k (a :: k). Proxy# a
proxy# :: Proxy# n)
instance forall (n :: Nat). KnownNat n => KnownInt ('Neg n) where
intSing :: SInt ('Neg n)
intSing = Integer -> SInt ('Neg n)
forall k (n :: k). Integer -> SInt n
SInt (Integer -> SInt ('Neg n)) -> Integer -> SInt ('Neg n)
forall a b. (a -> b) -> a -> b
$! Integer -> Integer
forall a. Num a => a -> a
negate (Proxy# n -> Integer
forall (n :: Nat). KnownNat n => Proxy# n -> Integer
natVal' (Proxy# n
forall k (a :: k). Proxy# a
proxy# :: Proxy# n))
intVal ::
forall n proxy. KnownInt n
=> proxy n
-> Integer
intVal :: proxy n -> Integer
intVal proxy n
_ =
case SInt n
forall k (n :: k). KnownInt n => SInt n
intSing :: SInt n of
SInt Integer
x -> Integer
x
intVal' ::
forall n. KnownInt n
=> Proxy# n
-> Integer
intVal' :: Proxy# n -> Integer
intVal' Proxy# n
_ =
case SInt n
forall k (n :: k). KnownInt n => SInt n
intSing :: SInt n of
SInt Integer
x -> Integer
x
data SomeInt =
forall n. KnownInt n =>
SomeInt (Proxy n)
instance Eq SomeInt where
SomeInt Proxy n
x == :: SomeInt -> SomeInt -> Bool
== SomeInt Proxy n
y = Proxy n -> Integer
forall k (n :: k) (proxy :: k -> *).
KnownInt n =>
proxy n -> Integer
intVal Proxy n
x Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Proxy n -> Integer
forall k (n :: k) (proxy :: k -> *).
KnownInt n =>
proxy n -> Integer
intVal Proxy n
y
instance Ord SomeInt where
compare :: SomeInt -> SomeInt -> Ordering
compare (SomeInt Proxy n
x) (SomeInt Proxy n
y) = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Proxy n -> Integer
forall k (n :: k) (proxy :: k -> *).
KnownInt n =>
proxy n -> Integer
intVal Proxy n
x) (Proxy n -> Integer
forall k (n :: k) (proxy :: k -> *).
KnownInt n =>
proxy n -> Integer
intVal Proxy n
y)
instance Show SomeInt where
showsPrec :: Int -> SomeInt -> ShowS
showsPrec Int
p (SomeInt Proxy n
x) = Int -> Integer -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
p (Proxy n -> Integer
forall k (n :: k) (proxy :: k -> *).
KnownInt n =>
proxy n -> Integer
intVal Proxy n
x)
instance Read SomeInt where
readsPrec :: Int -> ReadS SomeInt
readsPrec Int
p String
xs = (Integer -> SomeInt) -> (Integer, String) -> (SomeInt, String)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Integer -> SomeInt
someIntVal ((Integer, String) -> (SomeInt, String))
-> [(Integer, String)] -> [(SomeInt, String)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> ReadS Integer
forall a. Read a => Int -> ReadS a
readsPrec Int
p String
xs
data SomeIntWithDict =
forall n. SomeIntWithDict (SInt n)
(Proxy n)
someIntVal :: Integer -> SomeInt
someIntVal :: Integer -> SomeInt
someIntVal Integer
x = SomeIntWithDict -> SomeInt
forall a b. a -> b
unsafeCoerce (SomeIntWithDict -> SomeInt) -> SomeIntWithDict -> SomeInt
forall a b. (a -> b) -> a -> b
$ SInt Any -> Proxy Any -> SomeIntWithDict
forall k (n :: k). SInt n -> Proxy n -> SomeIntWithDict
SomeIntWithDict (Integer -> SInt Any
forall k (n :: k). Integer -> SInt n
SInt Integer
x) Proxy Any
forall k (t :: k). Proxy t
Proxy