What is the difference between `ix` and `at` in the Lens library of Haskell

前端 未结 1 1520
醉话见心
醉话见心 2020-12-16 10:11

All I know is that one works and the other doesn\'t.

Context: I have one data structure F which contains a Data.Map.Map k S

相关标签:
1条回答
  • 2020-12-16 11:14

    That at and ix are different is already noticable if you look at the available instances for the classes containing these functions:

    • instances of At: Map, IntMap, HashMap
    • instances of Ixed: [a], Map, ByteString, Text, and a lot more

    All instances if At are also an instance of Ix, but not all instances of Ix are also an instance of At.

    So what's the difference between them? 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
    

    (There is also a shortcut for a .~ Just b, a ?~ b)

    Technically, this difference comes from the fact that 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.

    You can always derive ix from at:

    ixAt = at . traverse
    

    The same definition is already in lens, except it's using (<.) for composition to keep the index from at. (at and ix are both indexed lenses / traversals).

    Off-topic: Most operators from lens also have infix names, you can find a (incomplete) table at: https://github.com/ekmett/lens/wiki/Operators

    0 讨论(0)
提交回复
热议问题