Haskell 获取数据构造函数的类型
Haskell get types of Data Constructor
我想知道是否给定一个构造函数,例如:
data UserType = User
{ username :: String
, password :: String
} -- deriving whatever necessary
对我来说最简单的方法是在 [("username", String), ("password", String)]
的行中获得一些东西,而不是手动编写它。现在对于这个具体的例子来说,只写它是可以的,但是对于一个有很多不同字段的复杂数据库模型来说,它会很烦人。
到目前为止,我已经查看了 Typeable
和 Data
,但到目前为止,我发现的最接近的是:
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)
我想知道是否给定一个构造函数,例如:
data UserType = User
{ username :: String
, password :: String
} -- deriving whatever necessary
对我来说最简单的方法是在 [("username", String), ("password", String)]
的行中获得一些东西,而不是手动编写它。现在对于这个具体的例子来说,只写它是可以的,但是对于一个有很多不同字段的复杂数据库模型来说,它会很烦人。
到目前为止,我已经查看了 Typeable
和 Data
,但到目前为止,我发现的最接近的是:
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)