我有一个数据结构,可以理解为类似于Data.Map
它将一种类型的键映射到另一种类型的值。我想Control.Lens.At
为这种类型编写一个实例,但我似乎永远无法满足所有要求。
给定Struct k v
, lookup
,和insert
,我必须做什么才能工作?update
delete
instance At (Struct k v)
我有一个数据结构,可以理解为类似于Data.Map
它将一种类型的键映射到另一种类型的值。我想Control.Lens.At
为这种类型编写一个实例,但我似乎永远无法满足所有要求。
给定Struct k v
, lookup
,和insert
,我必须做什么才能工作?update
delete
instance At (Struct k v)
该at
方法应该返回一个给定索引的索引镜头作为输入你的结构和行为是这样的:
Nothing
,否则返回结构中键处的值。Nothing
,则从结构中删除键,否则将其设置(或创建它,如果它不存在)为Just
.at
.这导致以下代码满足您的要求:
instance At (Struct k v) where
at key = ilens getter setter
where getter = (key, lookup key)
setter s Nothing = delete key s
setter s (Just newValue) = insert key newValue s
我用lens
构造一个镜头ilens
来从一个吸气剂和一个设置器构造一个索引镜头。我还假设您的函数具有以下类型:
lookup :: k -> Struct k v -> Maybe v
delete :: k -> Struct k v -> Struct k v
insert :: k -> v -> Struct k v -> Struct k v
-- Insert should override the key when it's already there
您仍然必须定义IxValue
和Index
类型族实例:
type instance IxValue (Struct k v) = v -- A (Struct k v) contains values of type v
type instance Index (Struct k v) = k -- A (Struct k v) has keys of type k.
编辑:实际上,必须返回一个索引镜头,而不仅仅是一个镜头。我还混淆了 setter 参数的顺序。