2015-01-22 8 views
8

W bibliotece soczewek Haskella, ix i element oba biorą Int mogą być stosowane np. do odczytu lub zapisu elementu listy w pewnym wskaźnikiem, jak toJaka jest różnica między ix i elementem w bibliotece soczewki Haskella

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

i podobnie:

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

Jaka jest różnica między element i ix?

Odpowiedz

11

Dzięki ix można indeksować nie tylko według numeru, ale np. klucz w Mapach. Indeks element w rozkazie Traverse.

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

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

Różnica jest jeszcze bardziej oczywista dzięki np. IntMap

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

element definiuje pracować z rodzajami Traversable klasy, a nawet członków klasy, które biblioteka obiektyw nie wiedzieć. W związku z tym używa tylko funkcji Traversable, aby uzyskać dostęp do wartości, która nie ma pojęcia żadnego typu indeksu związanego z typem wartości. Jako takie, obsługiwane są tylko indeksy Int, co daje elementy w zwykłej kolejności ruchu.

element również daje IndexedTraversal, dając dodatkowe sposoby obsługi indeksów.

ix jest zdefiniowany tylko dla typów, o których wie biblioteka obiektywów, ale w zamian może korzystać z różnych typów indeksów zależnych od typu wartości.

Dla list dają ten sam wynik. Ale można zauważyć różnicę, np. dla 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 

Jak widać, z element mapa podano Int indeksów, natomiast z ix jest on podany jako typ klucza indeksu i próbuje przełączyć że około daje błąd typu.

3

element działa, przechodząc całą strukturę, licząc elementy i przechodząc przez element z indeksem docelowym. Dlatego zawsze ma złożoność czasową O (n) w rozmiarze struktury i działa tylko z indeksami Int.

W przeciwieństwie do tego, ix ma własną klasę Ixed, a instancje polegają na wyszukiwaniu/modyfikowaniu operacji określonych struktur danych. Na przykład: ix dla Data.Sequence to O (log n).

Jednak ix działa tylko w określonych strukturach danych, a elementOf współpracuje z dowolnym Traversal, Lens lub Iso, na przykład:

[0..10] ^? elementOf (reversed . each . filtered odd) 1 
-- Just 7 
+0

Dzięki. +1 za wzmiankę o złożoności, naprawdę martwiłem się o to. To ma sens. Wydaje się więc, że powinniśmy używać ix tam, gdzie to możliwe. – Stephan