Doing in Spider
sieht unmöglich aus. Internal
Argumentation voraus.
In der Spider
Implementierung von Reflex
ist einer der möglichen Behavior
s, um den Wert zu ziehen.
data Behavior a
= BehaviorHold !(Hold a)
| BehaviorConst !a
| BehaviorPull !(Pull a)
A Pull
ed Wert besteht aus, wie der Wert zu berechnen, wenn nötig, pullCompute
und ein zwischengespeicherten Wert unnötige erneute Berechnung, pullValue
zu vermeiden.
data Pull a
= Pull { pullValue :: !(IORef (Maybe (PullSubscribed a)))
, pullCompute :: !(BehaviorM a)
}
die hässliche Umgebung von BehaviorM
Ignorieren, liftIO
hebt Benutzer IO
Berechnung die offensichtliche Art und Weise, es läuft, wenn die BehaviorM
Bedürfnisse abgetastet werden. In der Pull
wird Ihr Verhalten einmal beobachtet, aber nicht erneut beobachtet, da der zwischengespeicherte Wert nicht ungültig ist.
Der zwischengespeicherte Wert PullSubscribed a
besteht aus dem Wert a
, eine Liste von anderen Werten, die ungültig gemacht werden müssen, wenn dieser Wert ungültig ist, und einige langweilige Speicherverwaltung.
data PullSubscribed a
= PullSubscribed { pullSubscribedValue :: !a
, pullSubscribedInvalidators :: !(IORef [Weak Invalidator])
-- ... boring memory stuff
}
Ein Invalidator
ein quantifizierter Pull
, die die Speicherreferenz zu bekommen genug rekursiv invalidators zu lesen, um den zwischengespeicherten Wert zu Nothing
ungültig zu machen und zu schreiben.
Um ständig zu ziehen, möchten wir in der Lage sein, unsere BehaviorM
ständig ungültig zu machen. Bei der Ausführung hat die an die BehaviorM
übergebene Umgebung eine Kopie ihres eigenen Invalidators, der von den Abhängigkeiten von BehaviorM
verwendet wird, um sie ungültig zu machen, wenn sie selbst ungültig werden.
Von der internen Umsetzung von readBehaviorTracked
scheint es keine Möglichkeit zu sein, dass das eigene invalidator Verhalten (wi
) jemals in der Liste der Teilnehmer am Ende, die für ungültig erklärt werden, wenn sie abgetastet wird (invsRef
).
a <- liftIO $ runReaderT (unBehaviorM $ pullCompute p) $ Just (wi, parentsRef)
invsRef <- liftIO . newIORef . maybeToList =<< askInvalidator
-- ...
let subscribed = PullSubscribed
{ pullSubscribedValue = a
, pullSubscribedInvalidators = invsRef
-- ...
}
Außerhalb der Einbauten, wenn es eine Möglichkeit existiert ständig eine Probe Behavior
es würde eine MonadFix (PullM t)
Instanz oder gegenseitige Rekursion durch Fixieren von pull
und sample
:
onDemand :: (Reflex t, MonadIO (PullM t)) => IO a -> Behavior t a
onDemand read = b
where
b = pull go
go = do
sample b
liftIO read
mir nicht habe eine Reflex
Umgebung, um dies zu versuchen, aber ich denke nicht, dass die Ergebnisse schön sein werden.
Ich weiß nicht, wie ich tun soll, was Sie wollen, aber ich werde beobachten, dass das, wonach Sie fragen, semantisch sehr seltsam ist - die "Bedeutung" eines solchen Verhaltens könnte sich ändern, je nachdem wie Beobachter mit dem Verhalten interagierten. Ich kenne Ihr FRP-Framework nicht genug, um es sicher zu wissen, aber ich würde erwarten, dass Verhaltensweisen unabhängig von der Beobachtung sein sollen - und die Tatsache, dass Beobachtung zur Laufzeit die Berechnung der "Bedeutung" verändern kann, ist nur ein Implementierungsdetail anstatt etwas, das dem Programmierer zur Verfügung gestellt werden soll. –
Ist es etwas wie "Signal" in Elm, das du erreichen willst? – zakyggaps