{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE RankNTypes #-}
module Data.TypedEncoding.Common.Util.TypeLits where
import GHC.TypeLits
import Data.Symbol.Ascii
import Data.Proxy
withSomeSymbol :: SomeSymbol -> (forall x. KnownSymbol x => Proxy x -> r) -> r
withSomeSymbol s fn = case s of
SomeSymbol p -> fn p
proxyCons :: forall (x :: Symbol) (xs :: [Symbol]) . Proxy x -> Proxy xs -> Proxy (x ': xs)
proxyCons _ _ = Proxy
type family Append (xs :: [k]) (ys :: [k]) :: [k] where
Append '[] xs = xs
Append (y ': ys) xs = y ': Append ys xs
type family AcceptEq (msg :: ErrorMessage) (c :: Ordering) :: Bool where
AcceptEq _ EQ = True
AcceptEq msg _ = TypeError msg
type family OrdBool (c :: Ordering) :: Bool where
OrdBool EQ = 'True
OrdBool _ = 'False
type family And (b1 :: Bool) (b2 :: Bool) :: Bool where
And 'True 'True = 'True
And _ _ = 'False
type family Or (b1 :: Bool) (b2 :: Bool) :: Bool where
Or 'False 'False = 'False
Or _ _ = 'True
type family If (b1 :: Bool) (a :: k) (b :: k) :: k where
If 'True a _ = a
If 'False _ b = b
type family Repeat (n :: Nat) (s :: Symbol) :: Symbol where
Repeat 0 s = ""
Repeat n s = AppendSymbol s (Repeat (n - 1) s)
type family Fst (s :: (k,h)) :: k where
Fst ('(,) a _) = a
type family Dupl (s :: k) :: (k,k) where
Dupl a = '(,) a a
type family Concat (s :: [Symbol]) :: Symbol where
Concat '[] = ""
Concat (x ': xs) = AppendSymbol x (Concat xs)
type family Drop (n :: Nat) (s :: Symbol) :: Symbol where
Drop n s = Concat (LDrop n (ToList s))
type family LDrop (n :: Nat) (s :: [k]) :: [k] where
LDrop 0 s = s
LDrop n '[] = '[]
LDrop n (x ': xs) = LDrop (n - 1) xs
type family Take (n :: Nat) (s :: Symbol) :: Symbol where
Take n s = Concat (LTake n (ToList s))
type family LTake (n :: Nat) (s :: [k]) :: [k] where
LTake 0 s = '[]
LTake n '[] = '[]
LTake n (x ': xs) = x ': LTake (n - 1) xs
type family TakeUntil (s :: Symbol) (stop :: Symbol) :: Symbol where
TakeUntil s stop = Concat (LTakeUntil (ToList s) stop)
type family LTakeUntil (s :: [Symbol]) (stop :: Symbol) :: [Symbol] where
LTakeUntil '[] _ = '[]
LTakeUntil (x ': xs) stop = LTakeUntilHelper (x ': LTakeUntil xs stop) (CmpSymbol x stop)
type family LTakeUntilHelper (s :: [Symbol]) (o :: Ordering) :: [Symbol] where
LTakeUntilHelper '[] _ = '[]
LTakeUntilHelper (x ': xs) 'EQ = '[]
LTakeUntilHelper (x ': xs) _ = (x ': xs)
type family Length (s :: Symbol) :: Nat where
Length x = LLengh (ToList x)
type family LLengh (s :: [k]) :: Nat where
LLengh '[] = 0
LLengh (x ': xs) = 1 + LLengh xs
type family LLast (s :: [Symbol]) :: Symbol where
LLast '[] = TypeError ('Text "Empty Symbol list not allowed")
LLast '[x] = x
LLast (_ ': xs) = LLast xs
type family Snoc (s :: [k]) (t :: k) :: [k] where
Snoc '[] x = '[x]
Snoc (x ': xs) y = x ': Snoc xs y
type family UnSnoc (s :: [k]) :: ([k], k) where
UnSnoc '[] = TypeError ('Text "Empty list, no last element")
UnSnoc '[x] = '(,) '[] x
UnSnoc (x ': xs) = UnSnocHelper x (UnSnoc xs)
type family UnSnocHelper (s :: k) (t :: ([k], k)) :: ([k], k) where
UnSnocHelper y ('(,) xs x) = '(,) (y ': xs) x