我想知道是否给了一个构造函数,例如:
data UserType = User
{ username :: String
, password :: String
} -- deriving whatever necessary
最简单的方法是让我获得[("username", String), ("password", String)]
的某些内容,而不仅仅是手动编写它。现在对于这个特定的例子来说,只需编写它就可以了,但是对于具有许多不同字段的复杂数据库模型来说,它会非常烦人。
到目前为止,我已查看了Typeable
和Data
,但到目前为止,我找到的最接近的是:
user = User "admin" "pass"
constrFields (toConstr user)
但是,这并没有告诉我类型,它只返回["username", "password"]
,它还要求我创建一个User实例。
答案 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)