Haskell镜头库中的ix和element有什么区别
What is the difference between ix and element in the Lens library of Haskell
在Haskell的镜头库中,ix
和element
都带有一个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]
element
和ix
有什么区别?
使用 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"
element
被定义为与 Traversable
class 的类型一起使用,甚至 class 镜头库不知道的成员。因此,它仅使用 Traversable
函数来访问值,这些函数没有任何特定于值类型的索引类型的概念。因此,仅支持 Int
个索引,以通常的遍历顺序给出元素。
element
还给出了一个 IndexedTraversal
,给出了一些处理索引的额外方法。
ix
仅针对镜头库知道的类型定义,但在 return 中它可以根据值的类型使用不同的索引类型。
对于列表,它们给出相同的结果。但是可以看出差异,例如对于 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
时,它被赋予键类型作为索引,并尝试将其切换为类型错误。
element
通过遍历整个结构、计算元素并遍历具有目标索引的元素来工作。因此,它在结构大小上始终具有 O(n) 的时间复杂度,并且它仅适用于 Int
索引。
相比之下,ix
有自己的classIxed
,实例依赖于特定数据结构的lookup/modify操作。例如,Data.Sequence
的 ix
是 O(log n)。
然而,ix
仅适用于特定的数据结构,而 elementOf
适用于任何 Traversal
、Lens
或 Iso
,例如:
[0..10] ^? elementOf (reversed . each . filtered odd) 1
-- Just 7
在Haskell的镜头库中,ix
和element
都带有一个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]
element
和ix
有什么区别?
使用 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"
element
被定义为与 Traversable
class 的类型一起使用,甚至 class 镜头库不知道的成员。因此,它仅使用 Traversable
函数来访问值,这些函数没有任何特定于值类型的索引类型的概念。因此,仅支持 Int
个索引,以通常的遍历顺序给出元素。
element
还给出了一个 IndexedTraversal
,给出了一些处理索引的额外方法。
ix
仅针对镜头库知道的类型定义,但在 return 中它可以根据值的类型使用不同的索引类型。
对于列表,它们给出相同的结果。但是可以看出差异,例如对于 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
时,它被赋予键类型作为索引,并尝试将其切换为类型错误。
element
通过遍历整个结构、计算元素并遍历具有目标索引的元素来工作。因此,它在结构大小上始终具有 O(n) 的时间复杂度,并且它仅适用于 Int
索引。
相比之下,ix
有自己的classIxed
,实例依赖于特定数据结构的lookup/modify操作。例如,Data.Sequence
的 ix
是 O(log n)。
然而,ix
仅适用于特定的数据结构,而 elementOf
适用于任何 Traversal
、Lens
或 Iso
,例如:
[0..10] ^? elementOf (reversed . each . filtered odd) 1
-- Just 7