{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE CPP #-}
#if MIN_VERSION_GLASGOW_HASKELL (8,6,0,0)
{-# LANGUAGE NoStarIsType #-}
#endif
module Haskus.Utils.Types.Nat
( Nat
, natValue
, natValue'
, KnownNat
, SomeNat (..)
, someNatVal
, sameNat
, CmpNat
, type (<=?)
, type (<=)
, NatEq
, NatNotEq
, Max
, Min
, IsZero
, IsNotZero
, type (+)
, type (-)
, type (*)
, type (^)
, Mod
, Log2
, Div
, NatBitCount
)
where
import GHC.TypeNats
import Haskus.Utils.Types.Bool
import Data.Proxy
natValue :: forall (n :: Nat) a. (KnownNat n, Num a) => a
{-# INLINABLE natValue #-}
natValue = fromIntegral (natVal (Proxy :: Proxy n))
natValue' :: forall (n :: Nat). KnownNat n => Word
{-# INLINABLE natValue' #-}
natValue' = natValue @n
type family NatEq a b :: Nat where
NatEq a a = 1
NatEq a b = 0
type family NatNotEq a b :: Nat where
NatNotEq a a = 0
NatNotEq a b = 1
type family Max (a :: Nat) (b :: Nat) where
Max a b = If (a <=? b) b a
type family Min (a :: Nat) (b :: Nat) where
Min a b = If (a <=? b) a b
type family NatBitCount (n :: Nat) :: Nat where
NatBitCount 0 = 1
NatBitCount n = NatBitCount' (n+1) (Log2 (n+1))
type family NatBitCount' v log2 where
NatBitCount' v log2 = log2 + NatNotEq v (2^log2)
type family IsZero (n :: Nat) :: Nat where
IsZero 0 = 1
IsZero _ = 0
type family IsNotZero (n :: Nat) :: Nat where
IsNotZero 0 = 0
IsNotZero _ = 1