如何解决具有组合查找和更新的地图记录?
一些伪代码:
data A = A
data B = B
data C = C
data D = D
data E = E
data F = F
data G = G
data A1 = A1 A B C
data A2 = A2 A
data A3 = A3 B C D
data A4 = A4 D E F
data A5 = A5 A1 A4 G
data Foo k = Foo
{
a1s :: Map.Map k A1,a2s :: Map.Map k A2,a3s :: Map.Map k A3,a4s :: Map.Map k A4,a5s :: Map.Map k A5,--and my attempted solution would use
-- e.g. [(A1,[(A,Unit),(B,(C,Unit)]),(A5,[(A1,Composite),(A4,(G,Unit) ]) ]
componentMap :: Map.Map Type (Set Type),-- e.g. [(A,[A1,A2]),(A1,[A5,A1]) ]
compositeMap :: Map.Map Type (Set Type)
}
我想构建某种看起来像这样的数据结构。从这里,我想:
-
lookup :: Foo k -> k -> Either FailureReason v
单个值;如果我们假设我们已经填充了地图,我想要lookup foo a1 :: A1
,但也需要传递实例,例如lookup foo a1 :: B
或lookup foo a5 :: A1
(因为这是getA1fromA5 $ lookup foo a5
的简写)和 { {1}}。我正在考虑lookup foo a5 :: B
但这可能有点过分了。 - 遍历类型,例如对
FailureReason = WrongType | NotPresent
的(索引)遍历,它应该命中(k,D)
中的所有内容
这可以实现为对 A3,A4,A5
和 componentMap
的递归搜索......只要它们是手动填充的。
由于上面看起来非常递归,我觉得这有一个 compositeMap
解决方案。可能是 GHC.Generics
吗?
或者我的解决方案是不需要 lens/optics + generic-lens/generic-optics
之类的,而只是编写一些遍历和镜头来索引我的结构?
问题变成了:这个功能是否已经存在于某个库中?如果不是,generics
是我正在寻找的工具吗?
解决方法
我假设您实际上并不需要多个映射——也就是说,给定的键应该只对应一个值,而不是 A1
映射中的 a1s
值和另一个 {来自 A2
地图等的 {1}} 值
此外,如果单个值中有多个特定类型的匹配项,您还没有说明要做什么,例如,如果您有类型的值:
a2s
并尝试检索或遍历 data A6 = A6 A3 A4
类型的术语。下面,我假设您只想检索和/或遍历遇到的“第一个”(例如,仅 D
中的 D
,忽略 A3
中的那个)。
无论如何,您可以使用 A4
泛型和来自 Data
的 lens
的一些助手来完成此操作。
不需要特殊的数据类型。一个普通的 Data.Data.Lens
就足够了,用 sum 类型来表示要存储的值的集合:
Map
要通过键查找(可能是深度嵌套的)值,我们可以使用 data Dat = D_A1 A1 | D_A2 A2 | D_A3 A3 | D_A4 A4 | D_A5 A5 deriving (Data)
type Foo k dat = Map k dat
中的 biplate
遍历:
lens
这里,lookupFoo :: (Ord k,Typeable v,Data dat) => k -> Foo k dat -> Maybe v
lookupFoo k foo = do
dat <- Map.lookup k foo
firstOf biplate dat
递归遍历词项 biplate
中所有类型为 v
的子词项。 dat
查询返回第一个匹配的术语,如果未找到术语,则返回 firstOf
。 (Nothing
块在 do
monad 中运行。)
要执行索引遍历,我们还可以使用 Maybe
,修改后使用 biplate
仅遍历第一个匹配项:
taking 1
完整代码:
itraverseFoo :: (Applicative f,Data dat) => (k -> v -> f v) -> Foo k dat -> f (Foo k dat)
itraverseFoo f foo = Map.traverseWithKey f' foo
where f' k dat = taking 1 biplate (f k) dat
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。