opencv-0.0.0.0: src/OpenCV/TypeLevel.hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
module OpenCV.TypeLevel
( -- * Kinds and types
DS(D, S), dsToMaybe
, Z(Z)
, (:::)((:::))
-- * Type level to value level conversions
, ToInt32(toInt32)
, ToNatDS(toNatDS)
, ToNatListDS(toNatListDS)
-- * Type functions
, Length
, Elem
, Relax
-- ** Predicates (constraints)
, In
, MayRelax
, All
, IsStatic
-- ** Type conversions
, DSNat
, DSNats
) where
import "base" Data.Int
import "base" Data.Proxy
import "base" Data.Type.Bool
import "base" GHC.Exts ( Constraint )
import "base" GHC.TypeLits
--------------------------------------------------------------------------------
-- Kinds and types
--------------------------------------------------------------------------------
-- | 'D'ynamically or 'S'tatically known values
--
-- Mainly used as a promoted type.
--
-- Operationally exactly the 'Maybe' type
data DS a
= D -- ^ Something is dynamically known
| S a -- ^ Something is statically known, in particular: @a@
deriving (Show, Eq, Functor)
-- | Converts a DS value to the corresponding Maybe value
dsToMaybe :: DS a -> Maybe a
dsToMaybe D = Nothing
dsToMaybe (S a) = Just a
-- | End of list
data Z = Z
-- | Heterogeneous lists
--
-- Implemented as nested 2-tuples.
--
-- > f :: Int ::: Bool ::: Char ::: Z
-- > f = 3 ::: False ::: 'X' ::: Z
data a ::: b = a ::: b
infixr 5 :::
--------------------------------------------------------------------------------
-- Type level to value level conversions
--------------------------------------------------------------------------------
class ToInt32 a where
toInt32 :: a -> Int32
-- | value level: identity
instance ToInt32 Int32 where
toInt32 = id
-- | type level: reify the known natural number @n@
instance (KnownNat n) => ToInt32 (proxy n) where
toInt32 = fromInteger . natVal
--------------------------------------------------------------------------------
-- | Type level to value level conversion of numbers that are either
-- 'D'ynamically or 'S'tatically known.
--
-- > toNatDS (Proxy ('S 42)) == S 42
-- > toNatDS (Proxy 'D) == D
class ToNatDS a where
toNatDS :: a -> DS Int32
-- | value level numbers are dynamically known
instance ToNatDS (proxy 'D) where
toNatDS _proxy = D
-- | type level numbers are statically known
instance (ToInt32 (Proxy n)) => ToNatDS (Proxy ('S n)) where
toNatDS _proxy = S $ toInt32 (Proxy :: Proxy n)
--------------------------------------------------------------------------------
class ToNatListDS a where
toNatListDS :: a -> [DS Int32]
instance ToNatListDS (proxy '[]) where
toNatListDS _proxy = []
instance (ToNatDS (Proxy a), ToNatListDS (Proxy as))
=> ToNatListDS (Proxy (a ': as)) where
toNatListDS _proxy = (toNatDS (Proxy :: Proxy a ))
: (toNatListDS (Proxy :: Proxy as))
--------------------------------------------------------------------------------
-- Type functions
--------------------------------------------------------------------------------
type family Length (xs :: [a]) :: Nat where
Length '[] = 0
Length (_x ': xs) = 1 + Length xs
type family Elem (e :: a) (xs :: [a]) :: Bool where
Elem _e '[] = 'False
Elem e (e ': _xs) = 'True
Elem e (_x ': xs) = Elem e xs
type In e xs = Elem e xs ~ 'True
type family DSNat (a :: ka) :: DS Nat where
DSNat Integer = 'D
DSNat Int32 = 'D
DSNat (Proxy n) = 'S n
DSNat (n :: Nat) = 'S n
type family DSNats (a :: ka) :: [DS Nat] where
DSNats Z = '[]
DSNats (x ::: xs) = DSNat x ': DSNats xs
DSNats ('[] :: [Nat]) = '[]
DSNats (x ': xs) = DSNat x ': DSNats xs
type family Relax (a :: DS ka) (b :: DS kb) :: Bool where
Relax x 'D = 'True
Relax ('S (x ': xs)) ('S (y ': ys)) = Relax x y && Relax ('S xs) ('S ys)
Relax ('S x) ('S y) = Relax x y
Relax x x = 'True
Relax x y = 'False
type MayRelax a b = Relax a b ~ 'True
-- type family LeDS_F (a :: Nat) (b :: DS Nat) :: Bool where
-- LeDS_F _a 'D = 'True
-- LeDS_F a ('S b) = a <=? b
-- type (.<=?) a b = LeDS_F a b ~ 'True
-- type LE a b = a <=? b ~ True
-- type GT a b = b <=? a ~ True
-- type family LengthDS (as :: DS [k]) :: DS Nat where
-- LengthDS 'D = 'D
-- LengthDS ('S xs) = 'S (Length xs)
-- type family MinLengthDS_F (a :: Nat) (bs :: DS [k]) :: Bool where
-- MinLengthDS_F _a 'D = 'True
-- MinLengthDS_F a bs = LeDS_F a (LengthDS bs)
-- type MinLengthDS a bs = MinLengthDS_F a bs ~ 'True
class PrivateIsStatic (ds :: DS a)
instance PrivateIsStatic ('S a)
class All (p :: k -> Constraint) (xs :: [k])
instance All p '[]
instance (p x, All p xs) => All p (x ': xs)
class (PrivateIsStatic ds) => IsStatic (ds :: DS a)
instance IsStatic ('S a)