{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE Trustworthy #-}
module Data.Parameterized.SymbolRepr
(
SymbolRepr
, symbolRepr
, knownSymbol
, someSymbol
, type GHC.Symbol
, GHC.KnownSymbol
) where
import GHC.TypeLits as GHC
import Unsafe.Coerce (unsafeCoerce)
import Data.Hashable
import Data.Proxy
import qualified Data.Text as Text
import Data.Parameterized.Classes
import Data.Parameterized.Some
newtype SymbolRepr (nm::GHC.Symbol)
= SymbolRepr { symbolRepr :: Text.Text
}
someSymbol :: Text.Text -> Some SymbolRepr
someSymbol nm = Some (SymbolRepr nm)
knownSymbol :: GHC.KnownSymbol s => SymbolRepr s
knownSymbol = go Proxy
where go :: GHC.KnownSymbol s => Proxy s -> SymbolRepr s
go p = SymbolRepr $! packSymbol (GHC.symbolVal p)
packSymbol str
| Text.unpack txt == str = txt
| otherwise = error $ "Unrepresentable symbol! "++ str
where txt = Text.pack str
instance (GHC.KnownSymbol s) => KnownRepr SymbolRepr s where
knownRepr = knownSymbol
instance TestEquality SymbolRepr where
testEquality (SymbolRepr x :: SymbolRepr x) (SymbolRepr y)
| x == y = Just (unsafeCoerce (Refl :: x :~: x))
| otherwise = Nothing
instance OrdF SymbolRepr where
compareF (SymbolRepr x :: SymbolRepr x) (SymbolRepr y)
| x < y = LTF
| x == y = unsafeCoerce (EQF :: OrderingF x x)
| otherwise = GTF
instance Eq (SymbolRepr x) where
_ == _ = True
instance Ord (SymbolRepr x) where
compare _ _ = EQ
instance HashableF SymbolRepr where
hashWithSaltF = hashWithSalt
instance Hashable (SymbolRepr nm) where
hashWithSalt s (SymbolRepr nm) = hashWithSalt s nm
instance Show (SymbolRepr nm) where
show (SymbolRepr nm) = Text.unpack nm
instance ShowF SymbolRepr