2015-01-22 5 views
8

In Haskells Linsen Bibliothek ist, und ixelement sowohl eine Int nehmen kann eine verwendet werden, z.B. zu lesen oder ein Listenelement zu einem bestimmten Index, wie diesesWas ist der Unterschied zwischen ix und das Element in der Linsen Bibliothek von Haskell

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

und in ähnlicher Weise schreiben:

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

Was ist der Unterschied zwischen element und ix?

Antwort

11

Mit ix können Sie nicht nur nach der Nummer indizieren, sondern z. Geben Sie die Karten ein. Der element Index in Traverse bestellen.

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

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

Der Unterschied ist noch deutlicher mit z.B. IntMap

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

element definiert mit Typen der Traversable Klasse, auch die Teilnehmer, die die Objektiv-Bibliothek kennen nicht funktionieren. Als solches verwendet es nur Traversable Funktionen, um auf den Wert zuzugreifen, die kein Konzept irgendeines für den Werttyp spezifischen Indextyps haben. Als solche werden nur Int Indizes unterstützt, die Elemente in der üblichen Durchquerungsreihenfolge geben.

element gibt auch eine IndexedTraversal, zusätzliche Wege im Umgang mit Indizes geben.

ix ist nur für Typen definiert, von denen die Linsenbibliothek Kenntnis hat, aber im Gegenzug können sie abhängig vom Typ des Werts verschiedene Indextypen verwenden.

Für Listen geben sie das gleiche Ergebnis. Aber der Unterschied kann z.B. für 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 

Wie Sie sehen können, mit element die Karte Int Indizes gegeben, während mit ix ist es den Schlüsseltyp als Index angegeben, und zu wechseln versuchen, dass um einen Typfehler gibt.

3

element funktioniert, indem Sie eine gesamte Struktur durchlaufen, die Elemente zählen und das Element mit dem Zielindex durchlaufen. Daher hat es immer die Zeitkomplexität O (n) in der Größe der Struktur, und es funktioniert nur mit Int Indizes.

Im Gegensatz dazu hat ix seine eigene Klasse Ixed, und Instanzen basieren auf den Nachschlage-/Änderungsoperationen der spezifischen Datenstrukturen. Zum Beispiel ist ix für Data.Sequence O (log n).

jedoch ix funktioniert nur auf bestimmte Datenstrukturen, während elementOf funktioniert mit jedem Traversal, Lens oder Iso, zum Beispiel:

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

Dank. +1 für die Erwähnung der Komplexität, war ich eigentlich besorgt darüber. Es macht absolut Sinn. Es scheint also, wir sollten ix wo immer möglich verwenden. – Stephan

Verwandte Themen