Haskell的Lens库中ix和element之间有什么区别

时间:2015-01-22 10:27:42

标签: haskell lens

在Haskell的镜头库中,ixelement都可以使用Int和在某个索引处读取或写入列表元素,如此

ghci> [1..10] ^? ix 4
Just 5
ghci> [1..10] & ix 4 .~ 1
[1,2,3,4,1,6,7,8,9,10]

同样地:

ghci> [1..10] ^? element 4
Just 5
ghci> [1..10] & element 4 .~ 1
[1,2,3,4,1,6,7,8,9,10]

elementix之间的区别是什么?

3 个答案:

答案 0 :(得分:11)

使用ix,您不仅可以按号码进行索引,还可以使用例如地图中的关键。 element订单中的Traverse索引。

λ> let m = Map.fromList [("foo", 'f'), ("bar", 'b')]
λ> m ^? ix "foo"
Just 'f'

λ> m ^? element 0 -- Map is ordered container!
Just 'b'

差异更明显,例如IntMap

λ> let im = IntMap.fromList [(1, "one"), (2, "two")]
λ> im ^? ix 1
Just "one"
λ> im ^? element 1
Just "two"

答案 1 :(得分:4)

element被定义为与Traversable类的类型一起使用,甚至是镜头库不知道的类成员。因此,它仅使用Traversable函数来访问该值,该值没有任何特定于值类型的索引类型的概念。因此,仅支持Int索引,以通常的遍历顺序给出元素。

element也提供了IndexedTraversal,提供了一些处理索引的额外方法。

ix仅针对镜头库所知的类型定义,但作为回报,它可以使用取决于值类型的不同索引类型。

对于列表,它们给出相同的结果。但可以看出差异,例如Data.Map

Prelude Control.Lens Data.Map> singleton "a" 3 ^? element "a"

<interactive>:19:28:
    Couldn't match expected type ‘Int’ with actual type ‘[Char]’
    In the first argument of ‘element’, namely ‘"a"’
    In the second argument of ‘(^?)’, namely ‘element "a"’
    In the expression: singleton "a" 3 ^? element "a"

Prelude Control.Lens Data.Map> singleton "a" 3 ^? ix "a"
Just 3
Prelude Control.Lens Data.Map> singleton "a" 3 ^? element 0
Just 3
Prelude Control.Lens Data.Map> singleton "a" 3 ^? ix 0

<interactive>:22:23:
    Could not deduce (Num [Char]) arising from the literal ‘0’
    from the context (Num a)
      bound by the inferred type of it :: Num a => Maybe a
      at <interactive>:22:1-23
    In the first argument of ‘ix’, namely ‘0’
    In the second argument of ‘(^?)’, namely ‘ix 0’
    In the expression: singleton "a" 3 ^? ix 0

正如您所看到的,使用element时,地图会被赋予Int个索引,而使用ix时,会将密钥类型指定为索引,并尝试将其切换为类型错误。

答案 2 :(得分:3)

element通过遍历整个结构,计算元素并使用目标索引遍历元素来工作。因此,它总是具有结构大小的时间复杂度O(n),并且它仅适用于Int索引。

相反,ix有自己的类Ixed,实例依赖于特定数据结构的查找/修改操作。例如,ix的{​​{1}}为O(log n)。

但是,Data.Sequence仅适用于特定数据结构,而ix适用于任何elementOfTraversalLens,例如:

Iso