The name of the type is available as a type-level string on the metadata M1
wrapping the type.
We can get type name as a regular string using the symbolVal
function in GHC’s standard library.
In the example below we use it to define a function that can get the name of any type with a Generic
instance.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Example (main) where
import Data.Proxy (Proxy (Proxy))
import GHC.Generics (D, Generic, M1, Meta (MetaData), Rep, from)
import GHC.TypeLits (KnownSymbol, symbolVal)
-- | Return the name of any type with a `Generic` instance.
typeName :: (Generic a, GetTypeName (Rep a)) => a -> String
typeName val = getTypeName (from val)
class GetTypeName f where
getTypeName :: f p -> String
instance (KnownSymbol typename) =>
GetTypeName (M1 D ('MetaData typename m p n) f) where
getTypeName _ = symbolVal (Proxy :: Proxy typename)
-- Okay, let's try this out!
data ExampleType = ExampleValue deriving (Generic)
main :: IO ()
main = putStrLn (typeName ExampleValue) -- -> "ExampleType"
You can run this example yourself by copying it into a file called Example.hs
, then running runghc Example.hs
.