And undocumented causality loop in layout computation
The following is not a causality loop:
displayHeight >>= sample . current
..but this one is:
tile (fixed 1) $ displayHeight >>= sample . current
I guess this can be somewhat surprising to the user, since the semantics are not exactly explained in the documentation.
As a general rule, one should usually avoid sample in any widget code (not only here, but in reflex-dom as well), because it's strict in a way which interacts poorly with the way we use recursion to order widgets visually. It can be quite frustrating, because things will often work fine until you go and use your widget inside a larger application and suddenly get a mysterious causality loop at runtime coming from a sample that's a few layers down.
It's kind of an accident of the way they get constructed that the widget monads have MonadSample instances, and it's possible we ought to find a way to simply disable those in ordinary widget code. (The correct and safe place to use sample is typically inside the corresponding push/pull monads.)
It can be quite frustrating, because things will often work fine until you go and use your widget inside a larger application and suddenly get a mysterious causality loop at runtime coming from a sample that's a few layers down.
That is exactly my experience -- thank you for the relief of not being alone in the suffering! : -)
If you have a Dynamic and want to use its value from the widget code, usually you want to first make sure that the Dynamic is passed down as far as reasonable to the widget that it ought to have an impact on, and then possibly use dyn to switch widgets, if the whole structure of the widget is meant to change based on the value, or, more ideally, you just process it into other Dynamics and such (e.g. using fmap) that plug directly into the primitive widgets, for example, if some text or colours are meant to change based on it.
@cgibbard, by the way, I have hoogled for dyn, yet alas to no avail:
hoogle --count=1000 dyn | grep -w dyn
Language.Haskell.TH.Lib dyn :: Quote m => String -> m Exp
Language.Haskell.TH.Lib.Internal dyn :: Quote m => String -> m Exp
Apologies, I was thinking of https://hackage.haskell.org/package/reflex-dom-core-0.8.1.0/docs/Reflex-Dom-Widget-Basic.html#v:dyn
which for some reason is exposed in Reflex as networkView (this whole module is weirdly named, these functions have nothing to do with networks): https://hackage.haskell.org/package/reflex-0.9.3.0/docs/Reflex-Network.html