【问题标题】:Haskell Records- setting/getting using string fieldnameHaskell Records - 使用字符串字段名设置/获取
【发布时间】:2013-11-06 18:50:08
【问题描述】:

在许多情况下,能够通过其名称​​作为字符串设置/获取记录字段会很有用(例如,将记录转换为/从命令行参数、HTTP 标头、SQL查询结果,或将小部件存储在 GUI 树中的易于使用的记录中等)。函数可以有类型

setField::String->Val->Record->Record
getField::String->Record->Val
getFieldNames::Record->[String]

其中 Val 可能是可以转换为其他类型的东西(字符串、glib GValue,甚至是我描述的可转换对象here

我已经开始编写一个库来执行此操作,并计划将其贡献给社区(它需要一些 GHC 扩展,可能包括 TemplateHaskell)......

我的问题-这样的东西已经存在吗?有没有更好的方法从外部名称/值对填充记录?我找遍了,找不到。 (镜头是相关的,但不要使用字符串名称)。

我认为这会很有用,但不想重新发明轮子。

【问题讨论】:

  • 您可以查看 Aeson 库如何通过与 JSON 的自动转换来解决此问题,以实现 Generic 的类型。
  • 这似乎是个坏主意。当密钥不存在时会发生什么?无操作?也许打字?这比 Map 的包装器有什么好处?与Record 和某些记录类型(例如参见 aeson)进行具体化是合理的,但记录类型本身可能是愚蠢的。
  • Jozefg- 这些是任何命令行参数/SQL 查询结果/widget 集合库都必须处理的问题,但现在这一切都必须在每次使用时手动重做(即-必须编写代码才能使 System.Console.GetOpt 正常工作,难道您不想只使用包装在单个记录周围的预先编写的函数吗)。当然,您可以提供相同功能的 Maybe 版本(例如 head 与 listToMaybe)。关键是,我宁愿让一个库来处理这些错误情况,也不愿每次都记得自己处理。

标签: haskell


【解决方案1】:

您可以使用Vinyl 执行类似的操作,但您仍然需要创建强类型访问器。优点是类型系统包含足够的信息,以确保您永远不需要运行时处理Maybe-wrapped 查找失败。

从该链接复制一些相关示例

name     = Field :: "name"     ::: String
age      = Field :: "age"      ::: Int
sleeping = Field :: "sleeping" ::: Bool


jon = name =: "jon"
  <+> age =: 20
  <+> sleeping =: True

type LifeForm = ["name" ::: String, "age" ::: Int, "sleeping" ::: Bool]

jon :: PlainRec LifeForm

wakeUp :: (("sleeping" ::: Bool) ∈ fields) => PlainRec fields -> PlainRec fields
wakeUp = sleeping `rPut` False

jon' = wakeUp jon

> rGet name jon'
"jon"
> rGet sleeping jon
True
> rGet sleeping jon'
False

如果您不愿意做类似的事情,那么您可能最终会遇到某种运行时故障,这意味着您还不如拥有type Record = Map String Val

【讨论】:

  • 我对 Vinyl 进行了一些研究,但它似乎并没有满足我的要求。出现在类型中的字符串实际上是在编译时删除的,所以这意味着它们不能用于使用运行时字符串设置记录(我错过了什么吗?)。图书馆看起来很酷,但不相关。另外,我不同意静态类型的记录除了统一类型的 Map 之外没有任何优势。这个想法是立即设置字段的类型,从而为大多数程序获得静态类型的好处。
  • 你想要相位混合,我想。如果您希望运行时字符串成为有效的映射键,那么您将无法进行类型检查以确保它们在编译时是正确的。 Vinyl 的记录正好相反——它们在编译时是可检查的,因此是可擦除的。也许您可以在运行时将同质的 Vinyl Record 转换为 Map 以混合这些模式,但运行时组件不会有类型安全性。
  • 如果您想将运行时字符串反映到类型系统中并确保它们被唯一使用,您可以也许通过使用幻像类型参数技巧来解决这个问题类似于STs 参数。不过,我认为您无法创建类型级别的证据来证明两个运行时字符串相同。
猜你喜欢
  • 2012-01-29
  • 2012-01-17
  • 1970-01-01
  • 2020-04-08
  • 2014-04-24
  • 2011-12-17
  • 2014-10-20
  • 1970-01-01
  • 2020-03-24
相关资源
最近更新 更多