{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE Trustworthy #-}
module Data.Parameterized.SymbolRepr
(
SymbolRepr
, symbolRepr
, knownSymbol
, someSymbol
, SomeSym(SomeSym)
, viewSomeSym
, type GHC.Symbol
, GHC.KnownSymbol
) where
import GHC.TypeLits as GHC
import Unsafe.Coerce (unsafeCoerce)
import Data.Hashable
import Data.Kind ( Type )
import Data.Proxy
import qualified Data.Text as Text
import Data.Parameterized.Classes
import Data.Parameterized.Some
newtype SymbolRepr (nm::GHC.Symbol)
= SymbolRepr { SymbolRepr nm -> Text
symbolRepr :: Text.Text
}
someSymbol :: Text.Text -> Some SymbolRepr
someSymbol :: Text -> Some SymbolRepr
someSymbol Text
nm = SymbolRepr Any -> Some SymbolRepr
forall k (f :: k -> *) (x :: k). f x -> Some f
Some (Text -> SymbolRepr Any
forall (nm :: Symbol). Text -> SymbolRepr nm
SymbolRepr Text
nm)
knownSymbol :: GHC.KnownSymbol s => SymbolRepr s
knownSymbol :: SymbolRepr s
knownSymbol = Proxy s -> SymbolRepr s
forall (s :: Symbol). KnownSymbol s => Proxy s -> SymbolRepr s
go Proxy s
forall k (t :: k). Proxy t
Proxy
where go :: GHC.KnownSymbol s => Proxy s -> SymbolRepr s
go :: Proxy s -> SymbolRepr s
go Proxy s
p = Text -> SymbolRepr s
forall (nm :: Symbol). Text -> SymbolRepr nm
SymbolRepr (Text -> SymbolRepr s) -> Text -> SymbolRepr s
forall a b. (a -> b) -> a -> b
$! String -> Text
packSymbol (Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
GHC.symbolVal Proxy s
p)
packSymbol :: String -> Text
packSymbol String
str
| Text -> String
Text.unpack Text
txt String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
str = Text
txt
| Bool
otherwise = String -> Text
forall a. HasCallStack => String -> a
error (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
"Unrepresentable symbol! "String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
str
where txt :: Text
txt = String -> Text
Text.pack String
str
instance (GHC.KnownSymbol s) => KnownRepr SymbolRepr s where
knownRepr :: SymbolRepr s
knownRepr = SymbolRepr s
forall (s :: Symbol). KnownSymbol s => SymbolRepr s
knownSymbol
instance TestEquality SymbolRepr where
testEquality :: SymbolRepr a -> SymbolRepr b -> Maybe (a :~: b)
testEquality (SymbolRepr Text
x :: SymbolRepr x) (SymbolRepr Text
y)
| Text
x Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
y = (a :~: b) -> Maybe (a :~: b)
forall a. a -> Maybe a
Just ((a :~: a) -> a :~: b
forall a b. a -> b
unsafeCoerce (a :~: a
forall k (a :: k). a :~: a
Refl :: x :~: x))
| Bool
otherwise = Maybe (a :~: b)
forall a. Maybe a
Nothing
instance OrdF SymbolRepr where
compareF :: SymbolRepr x -> SymbolRepr y -> OrderingF x y
compareF (SymbolRepr Text
x :: SymbolRepr x) (SymbolRepr Text
y)
| Text
x Text -> Text -> Bool
forall a. Ord a => a -> a -> Bool
< Text
y = OrderingF x y
forall k (x :: k) (y :: k). OrderingF x y
LTF
| Text
x Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
y = OrderingF x x -> OrderingF x y
forall a b. a -> b
unsafeCoerce (OrderingF x x
forall k (x :: k). OrderingF x x
EQF :: OrderingF x x)
| Bool
otherwise = OrderingF x y
forall k (x :: k) (y :: k). OrderingF x y
GTF
instance Eq (SymbolRepr x) where
SymbolRepr x
_ == :: SymbolRepr x -> SymbolRepr x -> Bool
== SymbolRepr x
_ = Bool
True
instance Ord (SymbolRepr x) where
compare :: SymbolRepr x -> SymbolRepr x -> Ordering
compare SymbolRepr x
_ SymbolRepr x
_ = Ordering
EQ
instance HashableF SymbolRepr where
hashWithSaltF :: Int -> SymbolRepr tp -> Int
hashWithSaltF = Int -> SymbolRepr tp -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt
instance Hashable (SymbolRepr nm) where
hashWithSalt :: Int -> SymbolRepr nm -> Int
hashWithSalt Int
s (SymbolRepr Text
nm) = Int -> Text -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
s Text
nm
instance Show (SymbolRepr nm) where
show :: SymbolRepr nm -> String
show (SymbolRepr Text
nm) = Text -> String
Text.unpack Text
nm
instance ShowF SymbolRepr
data SomeSym (c :: GHC.Symbol -> Type) =
forall (s :: GHC.Symbol) . GHC.KnownSymbol s => SomeSym (c s)
viewSomeSym :: (forall (s :: GHC.Symbol) . GHC.KnownSymbol s => c s -> r) ->
SomeSym c -> r
viewSomeSym :: (forall (s :: Symbol). KnownSymbol s => c s -> r) -> SomeSym c -> r
viewSomeSym forall (s :: Symbol). KnownSymbol s => c s -> r
f (SomeSym c s
x) = c s -> r
forall (s :: Symbol). KnownSymbol s => c s -> r
f c s
x