【问题标题】:Convert array of tuples into data record将元组数组转换为数据记录
【发布时间】:2016-06-16 11:17:24
【问题描述】:

我有想要转换为数据记录的元组列表。元组具有类型 (Text, Text),其中第一项是键,第二项是值。

data User = User 
  { 
    id :: Text
  , name :: Text 
  }

toUser :: [(Text, Text)] -> User
toUser kvs = ???

是否可以在 Haskell 中通过字符串名称设置数据记录的字段名称,就像您通常可以在 C# 或 Java 中使用反射一样?

此外,我想避免通过列表重复查找每个字段,并通过列表迭代一次填充数据记录,但不确定这样做的最佳选择是什么。

编辑

输入列表将类似于[("id","foo"),("name","bar")],因此User 数据记录中的字段名称与列表中的键匹配。

【问题讨论】:

  • 你的意思是元组包含[("id","foo"),("name","bar")]?
  • @WillemVanOnsem 完全正确
  • 可以订购吗?
  • 是的,不幸的是

标签: haskell


【解决方案1】:

如果您只想遍历列表一次,我会将元组插入map,然后在地图中查找 ADT 的每个字段名称:

import qualified Data.Map as Map
import Data.Maybe (fromMaybe)

data User = User
  {
    id   :: String
  , name :: String
  } deriving Show

toUser :: [(String, String)] -> User
toUser xs = User (find "id") (find "name")
  where
    m = Map.fromList xs
    find name = fromMaybe "" $ Map.lookup name m

【讨论】:

  • 我认为 OP 正在寻找一种方法来简单地添加字段而无需添加额外的 find 语句,就像使用 C# 的反射或模板 Haskell 一样。
  • @WillemVanOnsem 是的,你是对的,即使基于地图的解决方案也可以,我更喜欢通用的东西......你提到了 Template Haskell,我听说建议避免使用它,但是如果它确实有效......
  • 是的,您需要使用模板 haskell 来为您生成所有 (find "x") (find "y") 代码。如果您可以在没有它的情况下逃脱,我会建议您这样做。此外,为不同的字段选择不同的默认值可能是一件好事(我只是在答案中使用了空字符串,而 ErikR 使用了“?”)
【解决方案2】:

@mb21的想法很容易实现:

import qualified Data.Map.Strict as M

toUser pairs = User idval nameval
    where m = M.fromList pairs
          idval = M.findWithDefault "?" "id" m
          nameval = M.findWithDefault "?" "name" m

但也许将其编写为更新函数会更好?

updateUser :: User -> [(Text,Text)] -> User
updateUser (User i n) pairs = User idval nameval
    where m = M.fromList pairs
          idval = M.findWithDefault  i m
          nameval = M.findWithDefault v "name" m

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-08-09
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
相关资源
最近更新 更多