2017-11-05 4 views
5

Kann ich eine Liste von Traversal verwenden? Der folgende Code:Wie benutzt man eine Objektivliste?

f::[Int] -> [[Int]] 
f l = [l & i .~ 1 | i<-[ix 0], (l^? i) == Just 0] 

erzeugt einen Fehler:

• Couldn't match type ‘Const (Data.Monoid.First Int) [Int]’ 
        with ‘Identity [Int]’ 
     Expected type: ASetter [Int] [Int] Int Integer 
     Actual type: Getting (Data.Monoid.First Int) [Int] Int 
    • In the first argument of ‘(.~)’, namely ‘i’ 
     In the second argument of ‘(&)’, namely ‘i .~ 1’ 
     In the expression: l & i .~ 1 

bei this question Blick Ich glaube, ich muss irgendwie explizit einen Typ i geben, aber jeder mein Versuch fehlschlägt.

Antwort

3

Das Problem besteht nicht darin, den Typ explizit anzugeben. Jedes Mal, wenn Sie einen Container mit Objektiven oder Traversalen haben möchten (Objektiv innerhalb des Paares, Objektiv in der Liste, Objektiv innerhalb Maybe), müssen Sie ReifiedLens verwenden.

Sehen Sie diese Frage zur Erklärung:

Why do we need Control.Lens.Reified?

So sollte Ihr Beispiel wie folgt geschrieben werden:

import Control.Lens 

f :: [Int] -> [[Int]] 
f l = [ l & i .~ 1 
     | Traversal i <- [Traversal $ ix 0] 
     , l ^? i == Just 0 
     ] 

Note that here Traversal is a constructor of type ReifiedTraversal .

Und es funktioniert wie folgt:

ghci> f [0,0,0] 
[[1,0,0]] 
+0

Danke vielmals! Gibt es übrigens eine Bibliotheksfunktion, die alle Indizes einer Liste zurückgibt? Etwas wie dieses: 'indicesOf l = [Traversal $ ix i | i <- [0..Länge 1 - 1]] ' –