Haskell获取Data Constructor的类型

时间:2016-03-08 21:22:59

标签: haskell introspection

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

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

最简单的方法是让我获得[("username", String), ("password", String)]的某些内容,而不仅仅是手动编写它。现在对于这个特定的例子来说,只需编写它就可以了,但是对于具有许多不同字段的复杂数据库模型来说,它会非常烦人。

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

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

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

1 个答案:

答案 0 :(得分:3)

我刚刚使用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)