Haskell 动态检索数据类型的值

Haskell 动态检索数据类型的值,haskell,generic-programming,Haskell,Generic Programming,我正在使用该模块在运行时动态获取某些数据类型的数据。假设a有一个数据类型,比如dataplace=Place{name::Text,description::Text}派生(data): 我可以用toConstr(Place“Some Place”“Bla”)检索它的构造函数,这将给我Place 我可以用constrFields$toConstr(Place“Some Place”“Bla”)检索它的标签字段,这将给我[“name”,“description”] 现在我需要的是得到我用来构造

我正在使用该模块在运行时动态获取某些数据类型的数据。假设a有一个数据类型,比如
dataplace=Place{name::Text,description::Text}派生(data)

  • 我可以用
    toConstr(Place“Some Place”“Bla”)
    检索它的构造函数,这将给我
    Place
  • 我可以用
    constrFields$toConstr(Place“Some Place”“Bla”)
    检索它的标签字段,这将给我
    [“name”,“description”]
现在我需要的是得到我用来构造位置的值,所以对于
Place“Some Place”“Bla”
我想提取类似
[“Some Place”,“Bla”]
,问题是在我的代码中,我不知道这个数据值是
位置
,它可以是派生
数据
类的任何数据类型。Icn代码:

getValuesOfDataValue :: (Data a) => a -> [String]
getValuesOfDataValue a =
    -- some magic generic function

data Place = Place {name :: Text, description :: Text} deriving (Data)
 -- the code below should evaluate to ["Some place", "Bla"]
getValuesOfDataValue (Place "Some place" "Bla")

data SomeType = SomeType {num :: Integer, num2 :: Integer} deriving (Data)
 -- the code below should evaluate to [300, 500]
getValuesOfDataValue (SomeType 300 500)
我怎样才能做到这一点


注意:
getValuesOfDataValue
不必返回一个精确的[String]类型,它只需要将值打包在一些东西中。

使用
Typeable
家族中的
cast
(回想一下,
Data
Typeable
的子类)

以动态类型的编程语言为例

如果您事先不知道需要哪种类型,还可以从
syb
包中使用
gshow
对值进行字符串化:

λ> :set -package syb
λ> import Data.Generics.Text
λ> data Triple = Triple Text Text Int deriving (Data)
λ> gmapQ gshow (Triple "a" "b" 1821)
["(pack \"a\")","(pack \"b\")","(1821)"]
不过,我要警告您:事先不知道需要哪种类型严重限制了泛型的使用。并不是所有的东西都能被细线化,即使它们被细线化了,也很难看(如上图所示)。即使知道你想要什么类型的白名单,也会对你有很大帮助:

λ> import Control.Arrow
λ> :set -XScopedTypeVariables
λ> let show' (proxy :: Proxy a) = Kleisli (\x -> show <$> (cast x :: Maybe a))
λ> gmapQ (runKleisli (show' (Proxy :: Proxy Int) <+> show' (Proxy :: Proxy Text))) (Triple "a" "b" 1821)
["a","b","1821"]

它的基本大小写是
String->ShowS
,因此每当它碰到一个字符串时,它就知道返回它并终止它。在不了解更多关于您的问题领域的详细信息的情况下,我会对您说,走出去,使用相同的策略构建您自己的
gshow
。在非常一般的情况下,如果您要打包每种类型,可能没有答案,但可能存在特定任务的特定内容。

请提供更多/更好的代码。顶级
let
s不是合法的Haskell,而且还不清楚
constrFields
应该做什么。如果您为
p
c
等提供类型,也会对我们双方都有帮助。请查看
gfoldl
。请添加一些描述您所面临问题的有效Haskell代码。我确实没有收到要求有效代码的注释,因为我提供的注释只是为了概念化问题,你可以认为它是假的哈斯克尔。你们没明白最后一段提到的问题吗?显然,皮鲁雷斯完全理解这一点。无论如何,我将对这个问题进行编辑和改进。@PyRulez如果你能提供一些非常简单的例子,我将不胜感激,无论如何,我会看一看,因为它似乎就是我要找的,thanx;)它可以工作,但是必须指定类型(:[可能是任何类型])会带来另一个复杂程度,因为我必须动态地查找这些类型(请记住,代码没有处理
三元组或任何其他类型的线索)。无论如何,thx;)
λ> import Control.Arrow
λ> :set -XScopedTypeVariables
λ> let show' (proxy :: Proxy a) = Kleisli (\x -> show <$> (cast x :: Maybe a))
λ> gmapQ (runKleisli (show' (Proxy :: Proxy Int) <+> show' (Proxy :: Proxy Text))) (Triple "a" "b" 1821)
["a","b","1821"]
-- | Generic show: an alternative to \"deriving Show\"
gshow :: Data a => a -> String
gshow x = gshows x ""

-- | Generic shows
gshows :: Data a => a -> ShowS

-- This is a prefix-show using surrounding "(" and ")",
-- where we recurse into subterms with gmapQ.
gshows = ( \t ->
                showChar '('
              . (showString . showConstr . toConstr $ t)
              . (foldr (.) id . gmapQ ((showChar ' ' .) . gshows) $ t)
              . showChar ')'
         ) `extQ` (shows :: String -> ShowS)