Während ich an einem Zustand namens AppState
arbeite, möchte ich die Anzahl der Instanzen beobachten. Diese Instanzen haben unterschiedliche IDs des Typs InstanceId
.So verwenden Sie Objektive, um einen Wert in einer Karte nachzuschlagen, zu erhöhen oder auf einen Standardwert zu setzen
Deshalb mein Zustand Blick mag diese
import Control.Lens
data AppState = AppState
{ -- ...
, _instanceCounter :: Map InstanceId Integer
}
makeLenses ''AppState
Die Funktion Spur von Zählungen zu halten, sollte 1 ergeben, wenn keine Instanz mit angegebener ID wird vor und n + 1
anders gezählt:
import Data.Map as Map
import Data.Map (Map)
countInstances :: InstanceId -> State AppState Integer
countInstances instanceId = do
instanceCounter %= incOrSetToOne
fromMaybe (error "This cannot logically happen.")
<$> use (instanceCounter . at instanceId)
where
incOrSetToOne :: Map InstanceId Integer -> Map InstanceId Integer
incOrSetToOne m = case Map.lookup instanceId m of
Just c -> Map.insert instanceId (c + 1) m
Nothing -> Map.insert instanceId 1 m
Während die oben Code funktioniert, gibt es hoffentlich eine Möglichkeit, es zu verbessern. Was ich nicht mag:
- I
instanceCounter
zweimal die Karte evozieren haben (zuerst für die Einstellung, dann wird der Wert für das Erhalten) - ich
fromMaybe
verwenden, wo immerJust
zu erwarten ist (so könnte ich auch gebrauchen) - Ich verwende keine Linsen für das Nachschlagen und Einfügen in . Der Grund dafür ist, dass
at
nicht den Fall behandeln kann, in demlookup
Nothing
ergibt, sondern stattdessenfmap
s überMaybe
.
Vorschläge für Verbesserungen?
Ich habe das Gefühl, dass ich 'at' noch nicht ganz verstanden habe ... jetzt sieht das' Just ... Just' überflüssig aus. Ich muss etwas mehr experimentieren, aber das ist tatsächlich das, wonach ich gesucht habe. –
OK, also war der Schlüssel für mich, die Funktion [alter] (http://hackage.haskell.org/package/containers-0.5.6.3/docs/Data-Map-Strict.html#v:alter) zu verstehen hat in seiner Signatur eine Funktion 'Maybe a -> Maybe a' um Kartenwerte zu setzen oder zu löschen. –
Und in Bezug auf die Verbesserung, die Antworten von Glguy übertrifft Ihre. Es tut uns leid! –