如何统一提取Haskell记录中的字段名称和值 [英] How to generically extract field names and values in Haskell records

查看:89
本文介绍了如何统一提取Haskell记录中的字段名称和值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


$ b

  { - #LANGUAGE DeriveDataTypeable# - } $ b $我最近得知我可以在Haskell中执行以下操作: b 
import Data.Data

data MyRecord = MyRecord
{field1 :: Int
,field2 :: String
,field3 :: String

$ main = print $ constrFields(toConstr(MyRecord 5HelloWorld))



这会给我以下信息:

  [ field1,field2,field3] 

我该怎么做对于记录中的值,如下所示:

  [5,Hello,World ] 

我在问,因为我正在使用 Aeson
$ p $ {
field1:5,
code> field2:Hello,
field3:World
}

然后像这样生成Haskell代码:

  field1 :: Int 
field1 = 5

field2 :: String
field2 =Hello

field3 :: String
field3 =世界

我如何一般地解开给定记录中的所有值,就像我可以解开我的记录的字段名称?

解决方案

您的第一个问题可以回答。如果您很乐意将数据类型的所有值转换为字符串,那么您确实可以使用通用编程库(例如, generics-sop

 { - #LANGUAGE DeriveGeneric,FlexibleContexts# - } 

将合格的GHC.Generics导入为G
import Generics.SOP

数据MyRecord = MyRecord
{field1 :: Int
,field2 :: String
,field3 :: String
}派生(Show,Eq,G.Generic)

实例Generic MyRecord

stringValues ::
(Generic a,All2 Show(Code a))
=> a - > [String]
stringValues a =
hcollapse(hcmap(Proxy :: Proxy Show)(\(I x) - > K(show x))(from a))

test :: [String]
test = stringValues(MyRecord 5Helloworld)

现在在GHCi:

  GHCi>测试
[5,\Hello \,\world \]

$ b但是,如果您的目标是维护原始类型,那么这会更困难,因为结果类型必须是异类列表(实际上泛型 - sop 在使用 hcollapse )转换回正常列表之前在内部使用。



我不完全清楚你真的想达到什么目的。很可能有一个更直接的解决方案。


I recently learned that I can do the following in Haskell:

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Data

data MyRecord = MyRecord
  { field1 :: Int
  , field2 :: String
  , field3 :: String
  } deriving (Show,Eq,Data,Typeable)

main = print $ constrFields (toConstr (MyRecord 5 "Hello" "World"))

This will give me the following:

["field1","field2","field3"]

How can I do the same thing for the values in a record, like this:

["5","Hello","World"]

I'm asking because I'm using Aeson to take simple JSON like this:

{
  "field1":5,
  "field2":"Hello",
  "field3":"World"
}

And generate Haskell code like this:

field1 :: Int
field1 = 5

field2 :: String
field2 = "Hello"

field3 :: String
field3 = "World"

How can I generically unwrap all the values in a given record in the same way I can unwrap the field names of my records?

解决方案

Your first question can be answered. If you're happy to convert all the values of a datatype to strings, then you can indeed produce such a list with a generic programming library such as e.g. generics-sop:

{-# LANGUAGE DeriveGeneric, FlexibleContexts #-}

import qualified GHC.Generics as G
import Generics.SOP

data MyRecord = MyRecord
  { field1 :: Int
  , field2 :: String
  , field3 :: String
  } deriving (Show, Eq, G.Generic)

instance Generic MyRecord

stringValues ::
     (Generic a, All2 Show (Code a))
  => a -> [String]
stringValues a =
  hcollapse (hcmap (Proxy :: Proxy Show) (\ (I x) -> K (show x)) (from a))

test :: [String]
test = stringValues (MyRecord 5 "Hello" "world")

Now in GHCi:

GHCi> test
["5","\"Hello\"","\"world\""]

However, if your goal is to maintain the original types, then this is more difficult, as the result type will have to be a heterogeneous list (which in fact generics-sop uses internally, before it is converted back into a normal list using hcollapse).

It's not entirely clear to me what you really want to achieve. It's quite possible that there's a much more straight-forward solution.

这篇关于如何统一提取Haskell记录中的字段名称和值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆