2013-08-24 45 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

    相關問題