Type Name

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.