2013-10-15 3 views
5

I insgesamt Karte vom Typ A Typ B habenControl.Lens Linse für eine Gesamtkarte

import qualified Data.Map as M 
import Data.Maybe 

tmGet k m = fromJust $ M.lookup k m 

tmSet k v = M.insert k v 

I Data.Map als Beispiel-Implementierung verwendet, aber es kann alles sein, z.B. ein Array oder sogar ein Bool -indexed Tupel:

tmGet True = fst 
tmGet False = snd 

Ich möchte eine Funktion haben eine Linse zu konstruieren:

(42, 665) ^. tmAt True == 42 
(42, 665) & tmAt False +~ 1 == (42, 666) 

Die Frage ist, wie konstruiere ich aus tmGet und tmSet (oder tmModify)?

Antwort

3

Wenn man sich the documentation for the Control.Lens module aussehen gibt es ein sehr praktisches Bild von den verschiedenen Teilen des Linse Pakets. Da Sie einen Lens konstruieren möchten, können Sie den Lens Teil des Diagramms betrachten. Die oberste gezeigte Funktion ist

lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b 

Dies baut ein Objektiv von einem Getter und einem Setter.

Die Funktion s -> a ist ein Getter - der Typ Unterschrift bedeutet, "Wenn Sie mir eine Datenstruktur s geben, werde ich einen a Wert daraus auswählen." Die s -> b -> t-Funktion ist der Setter, und die Typ-Signatur bedeutet: "Wenn Sie mir einen s und einen neuen Wert b geben, erstelle ich für Sie eine neue Struktur t." (Die Typen sind unterschiedlich, weil Linsen tatsächlich Arten der Dinge ändern können.)

Wenn Ihr Getter tmGet und Ihre Setter ist tmSet, Sie also eine Linse mit

tmAt :: Boolean -> Lens s t a b 
tmAt b = lens (tmGet b) (tmSet b) 

für was auch immer Ihre tatsächliche s konstruieren kann, t, a und b Parameter sind. Im Beispiel eines Tupels, wäre es

seine
tmAt :: Bool -> Lens (a, a) (a, a) a a 

(Mit anderen Worten, wenn Sie dem Objektiv eine Funktion a -> a geben, kann es ein (a, a) tupel in einer anderen (a, a) tupel verwandeln.)


Wenn Sie Lust sein wollen, können Sie auch als

tmAt = lens <$> tmGet <*> tmSet 
+0

Ha, das Applicative Form schön umschreiben kann, ist –

0

Sobald Sie definiert haben tmGet und tmSet vom Typ sein

tmGet :: k -> f v -> v 
tmSet :: k -> f v -> v -> f v 

können Sie eine Familie von Linsen, die durch das Objektiv Konstruktor lens mit parametrisierte Getter und Setter Fütterung. Hier ist, wie Sie es für ein Paar von einem in GHCI Bool

tmGet True = fst 
tmGet False = snd 

tmSet True (_,b) a = (a,b) 
tmSet False (a,_) b = (a,b) 

tmAt b = lens (tmGet b) (tmSet b) 

Jetzt indiziert tun würden

>>> (42,665) ^. tmAt True 
42 
>>> (42,665) & tmAt False +~ 1 
(42,666) 
Verwandte Themen