在Haskell的Lens库中,`ix`和`at`有什么区别?

Joh*_*ler 26 haskell haskell-lens

我所知道的是一个有效,另一个没有.

上下文: 我有一个数据结构F,其中包含Data.Map.Map k S另一个数据结构S.我的目标是建立一个Lens给定的F,k并将描述一个领域S.

困难在于密钥k可能不存在于地图中.这很好,该函数可以在Maybe中包装它的返回.但是,我无法通过使用Maybe传播镜头at.在阅读了很多Stack Overflow答案之后,我遇到了这个问题.

事实证明,更换atix解决我的问题类型,如果我还换成(^.)(^?).

问题: 似乎at并且ix做同样的事情,至少在这方面Map.两者都拿一把钥匙并给那个钥匙的价值一个'镜头'.但是,ix似乎与函数组合运算符很好(.).两者有什么区别?


关闭主题咆哮:

我像下一个人一样喜欢中缀运算符,但Control.Lens包看起来有点过分了.对于具有某些英文名称和某个键的新用户而言,会降低学习曲线.由于Lens库中使用了大量的包装器类,如果您还不知道发生了什么,则特别难以深入了解类型签名.为了天堂,我的代码开始看起来像Perl.

ben*_*ofs 22

atix不同已经noticable如果你看一下包含这些功能的类可用实例:

  • 实例At:Map,IntMap,HashMap
  • 实例Ixed:[a],Map,ByteString,Text等等

所有实例if At也是实例Ix,但不是所有实例Ix也是实例At.

那么它们之间的区别是什么?At用于容器,允许插入容器中不存在的键.这对于Map来说显然是可能的,但不是例如列表.仍然能够索引到列表并更改那里的Ix项目,不允许创建新项目,但当您尝试写入不存在的键时,"不执行任何操作".

>>> 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
Run Code Online (Sandbox Code Playgroud)

(还有一个快捷方式a .~ Just b,a ?~ b)

从技术上讲,这种差异来自于一个事实,即ix穿越,而at一个镜头.而且因为at是一个"回归"一个可能的东西的镜头,你不能用一个简单的"Something"镜头来构图.ix是一个具有0或1值的遍历,因此您可以像任何其他遍历一样编写ix(就像您可以编写的那样traverse . traverse).(^?)只需获取遍历的第一个值(头部).

你总是可以ixat:

ixAt = at . traverse
Run Code Online (Sandbox Code Playgroud)

相同的定义已经在镜头中,除了它(<.)用于合成以保持索引不在.(at并且ix都是索引镜头/遍历).

偏离主题:镜头中的大多数操作员也有中缀名称,您可以在以下网址找到(不完整)表格:https://github.com/ekmett/lens/wiki/Operators

  • 我认为"完全不同"是夸大它 - "ix k = at k".当两者都实施时,遍历`是一种法律.`at`提供了比`ix`更多的功能(但是`ix`是为更多类型实现的). (3认同)