- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想发送一些 JSON,其中包含从 (Database.Persist.Sql) 键到值的映射。显而易见的解决方案是使用 Map (Key x) v
,但这不是 ToJSON
的实例.
一些替代方案是:
Map k v
,返回Map Text v
(但在这里我会丢失一些类型信息)type JsonKey = Text
,和Map JsonKey v
,但这并没有真正更好ToJSON
实例。后者似乎是需要较少更改的一种,而且更干净。
另外,请注意,我只需要 ToJSON
实例,而不是 FromJSON
,所以我不需要整个往返。
所以,这就是我想写的:
import Database.Persist.Sql (Key)
instance ToJSON (ToJSON v => (Map (Key a) v))
假设Key
有一个友好的Show
实例(事实并非如此,但这只是一个细节)...我正要写:
instance ToJSON (ToJSON v => (Map (Key a) v)) where
toJSON m = toJSON $ mapKeysMonotonic show m
但我立即意识到这很糟糕(键就像整数):
> 9 < 10
True
> "9" < "10"
False
这违反了 mapKeysMonotonic
前提条件。
现在,与此同时,我可以使用 mapKeys
...但我试图思考,违反这一点有什么风险? mapKeys
显然效率较低。我明白这可能是不成熟的优化。
但我仍然想了解这会以何种方式崩溃......或者对于我有限的用例来说它是否确实安全。我唯一关心的是值(value)观是否丢失。我不在乎他们的顺序。
现在,this is instance (ToJSON v) => ToJSON (M.Map String v)
。它转换 Data.Map
到 Data.HashMap
这依赖于 mapHashKeyVals
...使用 Data.Map.foldrWithKey
我还考虑过使用HashMap (Key x) v
,以避免 N*log(N)
计算或mapKeysMonotonic
。但我仍然定义了 ToJSON 实例,显然没有 mapKeys
对于 HashMap
(可以理解,因为这需要重新计算所有哈希值,但我不确定这是否实际上比 mapKeys
更昂贵)
现在,我尝试了这个简单的示例:
> mapKeysMonotonic show $ fromList [(10,"a"), (9, "b"), (99, "c"), (100, "d")]
fromList [("9","b"),("10","a"),("99","c"),("100","d")]
自show
以来返回不同的 String
对于每个不同的 Int
,显然没有任何值丢失。现在的 map 可能已经不平衡了……但是后果是什么?我猜union
, difference
, intersection
可能会行为不当……但是遍历和折叠呢?在所有情况下这些仍然保留所有元素吗?
PS:我刚刚意识到另一个可能的解决方案可能是定义 instance ToJSON (ToJSON v => [(Key x, v)])
并将其转换为Map
在里面......但我想这将是一个重叠的实例
最佳答案
您可以使用Map.showTree
来检查 map 的二叉树结构。 mapKeysMonotonic
函数保持相同的树顺序,只是替换节点,因此任何涉及搜索树的访问器都会给出错误的结果。
不进行搜索的遍历很可能会起作用,但是使用这样的映射违反了数据结构的逻辑,这会导致困惑和错误。
要定义您的 ToJSON
实例,您不需要构建中间映射;您可以使用foldrWithKey
直接构造一个Value
。请注意,Aeson 中的 Object
构造函数只是 HashMap Text Value
。折叠本身的时间复杂度为 O(n),插入到 HashMap 中的时间(实际上)是常数。像这样的事情:
instance ToJSON v => ToJSON (Map (Key a) v) where
toJSON = Object . Map.foldrWithKey f mempty
where f = HashMap.insert . Text.pack . show
关于json - 违反mapKeysMonotonic前提条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31938589/
我是一名优秀的程序员,十分优秀!