Haskell的Lens库中`ix`和`at`有什么区别? [英] What is the difference between `ix` and `at` in the Lens library of Haskell
问题描述
上下文:
我有一个数据结构 F
其中包含 Data.Map.Map k S
到另一个数据结构 S
。我的目标是建立一个
Lens
,它给出 F
和 k
将描述 S
中的字段。
难度在于 k
可能不在地图中。这很好,函数可以在Maybe中包含它的返回值。不过,我无法通过中的使用Maybe传播镜头。阅读了很多堆栈溢出的答案后,我遇到了这一个。
事实证明,用 问题: 关闭主题Rant: 我和下一个人一样喜欢中缀运算符,但是Control.Lens包似乎有点过分了。对于有一些英文名字和某处键的新用户来说,会降低学习曲线。由于镜头库中使用的包装类数量庞大,如果您不知道发生了什么,则特别难以挖掘类型签名。 c $ c> At ix
取代中的我的类型问题 if 我也用
也是(^?)
替换了(^。)
。
看起来像在
和 ix
做同样的事情,至少就 Map
而言。双方都拿一把钥匙,并给这个钥匙上的价值赋予一个镜头。但是, ix
似乎在函数组合运算符(。)
中表现得很好。这两者之间有什么区别?
ix
是不同的,那么它已经不可用了:
的实例:Map,IntMap,HashMap
:[a],Map,ByteString,Text和更多
Ix
的一个实例,但并不是所有 Ix
也是 At
的一个实例。
那他们有什么区别? At
用于允许插入容器中不存在的键的容器。对于地图来说这显然是可能的,但不是例如。为一个列表。为了仍然能够索引到一个列表并更改那里的项目, Ix
不允许创建新项目,但是当您尝试写入时不会执行任何操作不存在的钥匙。
>>> Data.Map.fromList [('a',1)]&在'b'。〜只需4
fromList [('a',1),('b',4)] - 插入值
>>> Data.Map.fromList [('a',1)]& ix'b'。〜4
fromList [('a',1)] - 什么也不是,因为键不存在
(还有一个快捷键 您可以始终从 定义已经在镜头中,除非它使用 焦点话题:镜头中的大多数运算符也都有中缀名称,您可以在 https://github.com/ekmett/lens/wiki/Operators All I know is that one works and the other doesn't. Context:
I have one data structure The difficulty is that the key It turns out that replacing Question:
It seems like Off Topic Rant: I like infix operators as much as the next guy but the Control.Lens package seems to have gone a little overboard. For a new user having some English names and a key somewhere would lower the learning curve. Due to the huge number of wrapper classes used in the Lens library it is particularly difficult to dig through the type signatures if you don't already know what is going on. My code is starting to look like Perl for heaven sake. That All instances if So what's the difference between them? (There is also a shortcut for Technically, this difference comes from the fact that You can always derive The same definition is already in lens, except it's using Off-topic: Most operators from lens also have infix names, you can find a (incomplete) table at: https://github.com/ekmett/lens/wiki/Operators 这篇关于Haskell的Lens库中`ix`和`at`有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! a。〜只要b
, a?〜b $ c $在技术上,这种差异来自于这样的事实:
ix
是一个遍历,而 at
是镜头。而且因为在
是一个Lens,它返回一个Maybe Something,所以你不能用只需要一个普通的Something的镜头来组装它。 ix
是一个0或1值的遍历,所以您可以像任何其他遍历一样编写ix(就像您可以编写 traverse。traverse
)。
(^?)
只需要该遍历的第一个值(head)。
$ b $ at
:< ix
/ p>
ixAt = at。遍历
(< ;. )
用于合成以保持索引不变。 ( at
和 ix
都是索引镜头/遍历)。
F
which contains a Data.Map.Map k S
to another data structure S
. My goal was to build a Lens
that given an F
and k
would describe a field in S
.k
may not be present in the map. That's fine the function can wrap its return in Maybe. However I could not propagate a lens through a Maybe using at
. After reading a lot of Stack Overflow answers, I came across this one. at
with ix
solved my type problems if I also replaced (^.)
with (^?)
.at
and ix
do the same thing, at least with regard to Map
. Both take a key and give a 'Lens' to the value at that key. However, ix
seems to play nice with the function composition operator (.)
. What is the difference between the two?
at
and ix
are different is already noticable if you look at the available instances for the classes containing these functions:
At
: Map, IntMap, HashMapIxed
: [a], Map, ByteString, Text, and a lot moreAt
are also an instance of Ix
, but not all instances of Ix
are also an instance of At
. At
is for containers that allow inserting keys that are not present in the container. This is obviously possible for a Map, but not e.g. for a list. To still be able to index into a list and change items that are there, Ix
doesn't allow creating new items, but just "does nothing" when you try to write to a key that is not there.>>> Data.Map.fromList [('a', 1)] & at 'b' .~ Just 4
fromList [('a',1),('b',4)] -- Inserts value
>>> Data.Map.fromList [('a', 1)] & ix 'b' .~ 4
fromList [('a',1)] -- Does nothing because key is not present
a .~ Just b
, a ?~ b
)ix
is a Traversal whereas at
is a Lens. And because at
is a Lens that "returns" a Maybe Something, you cannot compose it with a lens that takes just a plain "Something". ix
is a Traversal with 0 or 1 values, so you can compose ix just like any other traversal (just like you can write traverse . traverse
). (^?)
just takes the first value (head) of that traversal. ix
from at
:ixAt = at . traverse
(<.)
for composition to keep the index from at. (at
and ix
are both indexed lenses / traversals).