Haskell 获取数据构造函数的类型

Haskell get types of Data Constructor

我想知道是否给定一个构造函数,例如:

data UserType = User
  { username :: String
  , password :: String
  } -- deriving whatever necessary

对我来说最简单的方法是在 [("username", String), ("password", String)] 的行中获得一些东西,而不是手动编写它。现在对于这个具体的例子来说,只写它是可以的,但是对于一个有很多不同字段的复杂数据库模型来说,它会很烦人。

到目前为止,我已经查看了 TypeableData,但到目前为止,我发现的最接近的是:

user = User "admin" "pass"
constrFields (toConstr user)

但这并没有告诉我类型,它只是 returns ["username", "password"] 并且还要求我创建一个 User 实例。

我刚刚使用 Data.Typeable 编写了一个函数,它可以让您将构造函数转换为其参数的 TypeRep 列表。结合 constrFields 你发现你可以将它们压缩在一起以获得你想要的结果:

{-# LANGUAGE DeriveDataTypeable #-}

module Foo where
import Data.Typeable
import Data.Typeable.Internal(funTc)

getConsArguments c = go (typeOf c)
   where go x = let (con, rest) = splitTyConApp x    
                in if con == funTc         
                   then case rest of (c:cs:[]) -> c : go cs
                                     _ -> error "arrows always take two arguments"
                   else []                      

给定 data Foo = Foo {a :: String, b :: Int} deriving Typeable,我们得到

*> getConsArguments Foo
[[Char],Int]

正如人们所希望的那样。


关于如何在不使用填充的数据类型值本身的情况下获取字段名称,这里有一个解决方案:

constrFields . head . dataTypeConstrs $ dataTypeOf (undefined :: Foo)