2013-08-24 43 views
20

我所知道的只有一个可以工作,另一个不可以。Haskell镜头库中的`ix`和`at`有什么区别

上下文: 我有含有Data.Map.Map k S到另一个数据结构S一个数据结构F。我的目标是建立一个Lens,给定Fk将描述S中的字段。

难点在于密钥k可能不在地图中。这很好,函数可以在Maybe中包含它的返回值。但是我无法通过Maybe使用at来传播镜头。在阅读了很多堆栈溢出的答案后,我碰到this one

事实证明,与ix更换at解决了我的问题类型,如果(^?)更换(^.)

问: 好像atix做同样的事情,至少对于Map。双方都拿一把钥匙,并给这个钥匙上的价值赋予一个“镜头”。但是,ix似乎与函数组合运算符(.)打得很好。两者有什么区别?


关闭主题咆哮:

我喜欢缀运营商多为未来的家伙但在Control.Lens包似乎过火了一点。对于有一些英文名字和某处键的新用户来说,会降低学习曲线。由于镜头库中使用的包装类数量庞大,如果您不知道发生了什么,则特别难以挖掘类型签名。我的代码开始在天堂看起来像Perl。

+0

你可以用'lens'没有一个单一的缀操作符。几乎每个运营商都只是一个非运营商名称的便捷别名 - 您不必使用它们(而我通常不会)。 – shachaf

+2

你不能做的就是尝试阅读理解其他人编写的代码,比如库示例文件夹。在大多数其他库中,在GHCi中复制一些代码并在其上跳动的过程显然比较困难。 –

+0

@shachaf这不是真的:某些非常有用的操作符不是以单词的形式存在的,即'%='(因为它在'do'块中使用而不是很糟糕)和'?〜'(非常糟糕,因为它在纯代码,如果你不想加载parens,需要从'$'切换到'&')。 – spopejoy

回答

19

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

  • 情况下地图,IntMap,:的At

    • 实例[ A],地图,字节串,文本,以及更多

    所有情况下,如果At也都是Ix的实例,但不是所有的我Ix的实例也是At的一个实例。

    那么他们之间有什么区别? At适用于允许插入不在容器中的密钥的容器。对于地图来说这显然是可能的,但不是例如。为一个列表。要仍然能够索引到列表并更改那里的项目,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 
    

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

    从技术上讲,这种差异来自于以下事实:ixTraversalatLens。而且因为at是一个Lens,它返回一个Maybe Something,所以你不能用只需要一个简单的“Something”的镜头来组合它。 ix是一个0或1值的遍历,所以你可以像任何其他遍历一样编写ix(就像你可以写traverse . traverse一样)。 (^?)只需要该遍历的第一个值(头部)。

    你总是可以从at获得ix

    ixAt = at . traverse 
    

    相同的定义is already in lens,除非它使用(<.)的组成保持从索引。 (atix都是索引镜头/遍历)。

    题外话:从镜头大多数运营商也有缀的名字,你可以找到在(不完全)表:https://github.com/ekmett/lens/wiki/Operators

  • +2

    我认为“完全不同”在夸大它 - 'ix k = at k。遍历“是一个法律,当两者都实施时。 'at'提供的功能要比'ix'严格得多(但'ix'实现了更多类型)。 – shachaf

    +0

    @shachaf你说得对。我编辑了答案。 – bennofs

    相关问题