如何使用类型系列将任何类型转换为Symbol?

She*_*rsh 5 haskell type-families

我想使用某些类型系列将任何类型转换为类型级别的字符串.

当然,我可以这样写:

type family ShowType (t :: Type) :: Symbol where
    ShowType Int    = "Int"
    ShowType String = "String"
    ...
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有一些现有的机制呢?我可以使用Typeable技术在运行时执行此操作.但是如何自动将任何类型转换为Symbol

Li-*_*Xia 1

没有适用于所有类型的通用解决方案。但也许您会发现以下内容很有趣。

您可以使用 的实例获取类型构造函数的名称Generic,尽管这不包括Int和 等基本类型Float。下面给出两种不同的方式:

{-# LANGUAGE AllowAmbiguousTypes#-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeApplications #-}

import Data.Proxy
import GHC.Generics
import GHC.TypeLits

-- Solution 1: Defines a type family that extracts the type
-- constructor name as a Symbol from a generic Rep.
-- Then it can be reified via GHC.TypeLits.symbolVal.

type family TyConName (f :: * -> *) :: Symbol where
  TyConName (M1 D ('MetaData name _mdl _pkg _nt) _f) = name

tyConName
  :: forall a s
  .  (Generic a, s ~ TyConName (Rep a), KnownSymbol s) => String
tyConName = symbolVal (Proxy @s)

-- Solution 2: Uses the GHC.Generics.datatypeName helper
-- (value-level string only).

tyConName'
  :: forall a d f p
  .  (Generic a, Rep a ~ D1 d f, Datatype d) => String
tyConName' = datatypeName (from @a undefined)

main = do
  print (tyConName @(Maybe Int))   -- "Maybe"
  print (tyConName' @(Maybe Int))  -- "Maybe"
Run Code Online (Sandbox Code Playgroud)