User Interface Entry: Microshocks Date: Tue Oct 6 00:17:23 EDT 2015 Touchscreens? Why not add neural feedback to hands? Microshocks to fingertips? Entry: Microshocks? :) Anwyays, status quo stuff.. Date: Thu Aug 17 21:57:01 EDT 2017 React: make the feedback loop bigger, so circular stuff gets "ironed out" into pure functional dependencies (compute view directly from model on each update). I like that idea, but it is also terribly unpractical, and for my current app I want to write most of the login in Erlang, server side, with client side being fairly dumb, close to DOM. But doing this for a bit I do wonder about all these architectural patterns. What is the real point behind MVC and MVVM etc... So many, so it seems there is little consensus. https://stackoverflow.com/questions/667781/what-is-the-difference-between-mvc-and-mvvm The basic MVCVM guidelines we follow are: Views display a certain shape of data. They have no idea where the data comes from. ViewModels hold a certain shape of data and commands, they do not know where the data, or code, comes from or how it is displayed. Models hold the actual data (various context, store or other methods) Controllers listen for, and publish, events. Controllers provide the logic that controls what data is seen and where. Controllers provide the command code to the ViewModel so that the ViewModel is actually reusable. In my case: - View = HTML (initial render + update) - ViewModel ? - Model = obvious - Controller = events MVC: Think database, HTML pages, and code inbetween The main thrust of the Model/View/ViewModel architecture seems to be that on top of the data (”the Model”), there’s another layer of non-visual components (”the ViewModel”) that map the concepts of the data more closely to the concepts of the view of the data (”the View”). It’s the ViewModel that the View binds to, not the Model directly. some more here https://russelleast.wordpress.com/2008/08/09/overview-of-the-modelview-viewmodel-mvvm-pattern-and-data-binding/ But really, not much the wiser. Let's work from first principles. The applications I'm writing are all interfaces to procedures that happen over time. What they do is: - to display current configuration - allow it to edit - start procedure - visualize state changes as procedure progresses until done - optionally, provide output as a document What works well here is to build the editor separately. Have it do input validation. The rest of the application does not need to interfere apart from specifying consistency (types and possibly other constraints). Procedure starts are just buttons starting processes. This is the "model change event" coming from the ui. Progress updates are translations of events coming from the model. Download is trivial: a one-shot render of the current model state. There are two controllers, each corresponding to its own views - The editor, linking data store and constraints to display - The sequencer: start, display notifications, output document. What I'm doing is more like MVVM, because the view does not talk to the model directly. Anways, the boundaries are fuzzy. I have code that generates a representation by querying the model and filling in data templates to initialize the view (which has some methods that only do display and event generation). So maybe this is more like VM. https://martinfowler.com/eaaDev/PresentationModel.html Represent the state and behavior of the presentation independently of the GUI controls used in the interface Presentation Model pulls the state and behavior of the view out into a model class that is part of the presentation. So React is PM, but with a larger feedback cycle. https://news.ycombinator.com/item?id=10773824 Entry: React vs VM Date: Fri Aug 18 00:10:26 EDT 2017 Example: selection box together with +/- buttons. When +/- toggles, main display toggles and the selection box state changes. I assume that presentation model would update selection box from viewmodel, which has only one copy of the state. React would be the functional version of that. Entry: ViewModel Date: Fri Aug 18 00:18:14 EDT 2017 Running into a case where a viewmodel is needed. There are 3 view elements: - display pane that switches between different pages - selection box to select the page - +/- buttons (take this as single view) This is a nice example because there are 3 different kinds of views: display only, update only, update+display. The ViewModel will then be responsible of the state, - upon reception of event will update pane and selection box - can receive event from selection box or +/- buttons So "view" means here more generally a GUI object which receives modelview updates and/or sends events to modelview. From a dataflow point of view, the purpose of the viewmodel is to convert from networked views to star view-viewmodel, and so it is a complexity reduction (N^2 -> N+1). Entry: This OO terminology Date: Fri Aug 18 00:31:37 EDT 2017 I don't care about your objects. What I care about is to understand how the information flows through the system. That is much less arbitrary and easier to understand. It is about how the objects talk to each other. Their linkage. Entry: ViewModel Date: Fri Aug 18 01:39:09 EDT 2017 M: model state V: view state VM: viewmodel state V_i: view states VM = {p(M),V} V_i = f(V,p(M)) where p(M) is projection or presentation of model modelview code: - accept events from views to update V, possibly M - accept events from model to update p(M) still I don't see why this can't just be a controller. maybe because the views don't have their own state (only caches directly derived from VM state). The main idea is: views should not manage their own state. But inside this really is the React idea: project the presentation state onto the screen. Can I have a mini react? Entry: What React does Date: Sat Aug 19 00:52:01 EDT 2017 Is to optimize the "data push" from viewmodel/presentation model into the display. Entry: The 3-widget problem Date: Sat Aug 19 01:25:27 EDT 2017 - pane display - selector - +/- buttons presentation state: - current pane update: - set selector - set pane event: - selector - +/- button Entry: Presentation model and caches (push environment once) Date: Mon Aug 21 09:44:15 EDT 2017 It's ok to extend the presentation model with caches. Basically, widget redraw will get data from local cache. EDIT: 1. Keep presentation "bounce" complete: do not put incremental updates in the bouncer: each PM state pushes a full update to every widget that is registered. 2. For PM and widgets that are separated by high latency link, fill the widget's cache with anything that doesn't change (PM environment) and only send state updates, e.g. indices into that environment. 3. Allow widgets to be smart wrt. repaint or not. Entry: The trick is to use components Date: Wed Aug 23 09:28:01 EDT 2017 1. Draw or redraw from specification. 2. How to generate the spec then depends on the application Entry: Updates Date: Wed Aug 23 10:32:43 EDT 2017 Let's think about "server side React". What is really necessary is to encode changes in such a way that: 1. messages are diff-encoded, making them smaller 2. no unnecessary updates are sent What I need is a representation of a data structure edit. Entry: So I have a tree differ Date: Wed Aug 23 11:47:25 EDT 2017 Very simple -- does only recursive maps, but it is likely good enough. What problem does it solve? It "condenses" edits. EDIT: A better way to explain: it adds a decoupling step. It is easier to update a model, condense it into a simpler one, then "diff" that, than to directly translate the original "edits" into "view updates". So basically: "decouple edits from presentation updates". Another thing: it is the declarative model that sits between two state update models that live in different worlds. Entry: Current UI model Date: Wed Aug 23 18:37:59 EDT 2017 Controller state: - type and state of each input - add hoc state, accumulated during edits - presentation model Controller flow: - event comes in, state gets updated (also type-checked) - add hoc changes are made based on edit - presentation model is regenerated - PM is diffed against previously stored value - diff is converted to View update commands View: - initialized from initial controller state - each widget sends input change events to controller - view exposes stateful update events - view has local cache for constant data(*) (*) is really a special case to avoid having to diff very large data structures for data that never changes. could be part of diff just as well. Entry: Final word on user interfaces Date: Mon Aug 28 11:55:32 EDT 2017 1. Model View Presenter (MVP). Main point is that model and view are unaware of each other. 2. Use a fully declarative presentation tree model, and base the view updates on PM tree diff. Structure PM such that diffs correspond to updates of view widgets. This is MVP (presentation model, isolated M,V) and also unidirectional UI (data flows from ui events through model update to ui updates). I believe there is a continuum between diffing the presentation model, and diffing the declarative form of the final layout (e.g. React). Diffing is the bridge between declarative and imperative, which in reality has to always happen somewhere unless you always redraw everything (e.g. OpenGL animations). Entry: Time for another round: Init and diff Date: Thu Aug 31 18:25:48 EDT 2017 The above works, but it needs init and diff. Essentially, doing the work twice, unless you can find a way to somehow initialize from an "empty" or "invalid" presentation model. Also, the initial rendering needs to happen from the initial PM. If that's not possible, the PM is not precise enough! Entry: Control state vs presentation model Date: Fri Sep 1 10:50:37 EDT 2017 It seems I have a need for two parts: - Full control state, possibly inconsistent (bunch of widgets) - Presentation model Basically, there is a phase where the controller knows about a possibly inconsistent state (e.g. user has modified selector box, but the rest of the view is not updated yet). This state is short-lived, e.g. only visible inside the event handler, but needs to be representable. This means controller state can be _larger_ than the presentation model state. Entry: More general imperative "derivatives" Date: Mon Sep 4 23:32:55 EDT 2017 I'm still wondering how far this idea can be pushed. Especially the part where starting from an empty model becomes an option. Currently, how the diffing works, this requires the creation of an entire tree, which is not likely what is desirable. It's probably better to map to creation of empty nodes, and then fill them with children. Entry: Twitter thread on "derivatives" Date: Fri Sep 8 21:12:39 EDT 2017 https://twitter.com/tom_zwizwa/status/906316251559022592 Phil mentions "incremental lambda calculus". https://github.com/paf31/purescript-incremental http://www.informatik.uni-marburg.de/~pgiarrusso/ILC/ http://www.informatik.uni-marburg.de/~pgiarrusso/papers/pldi14-ilc-author-final.pdf Entry: doodling Date: Fri Sep 8 21:26:47 EDT 2017 https://twitter.com/tom_zwizwa/status/906316251559022592 Phil mentions "incremental lambda calculus". https://github.com/paf31/purescript-incremental http://www.informatik.uni-marburg.de/~pgiarrusso/ILC/ http://www.informatik.uni-marburg.de/~pgiarrusso/papers/pldi14-ilc-author-final.pdf Dah I really don't want to read it. I'm sure the basic idea is simple. Can I just reinvent it based on the hint that there is something here? This has to be about the chain rule. EDIT: Yes, the idea was simple. There are 4 rules that resemble the chain rule. See compsci.txt Given a function that maps one nested map into another (Erlang types), what exactly is a diff of a function? It is about this: T0 --> f(T0) | | V V T1 --> f(T1) Given any difference of the input, compute the difference of the output. Or find the function (T1-T0) -> (f(T1)-f(T0)) I have an explicit diff function already. Can I just "push that inside" any tree processing function? Some examples? T0 = #{ a => 1 }, T1 = #{ a => 2 }, f(#{a := X}) -> #{ a => X + 1} the map of the diffs is then {update,[a],1,2} -> {update,[a],2,3} The key here is really to define the difference / differential in the ordinary way: f(T1) - f(T0) D = ------------- T1 - T0 And give a meaning to "-" as tree diff. Is it possible to reconstruct the chain rule by making f to be a composition of functions? This is Conal's CCC stuff... It would help to make this more concrete. Let's fix the representation for now. Stick to actual XHTML and represent the structure as a nested list. #{ tag => div, attr => #{ style => "display: block" }, body => #{ id1 => ... id2 => ... }} The trick here is to abstract away all the ad-hoc attrib stuff as well. E.g. some attributes have inner syntax that also needs to be mapped to a tree. Also id attributes are better used as dictionary keys. Once this is done, there are only a couple operations, e.g.: - Moving things around - Duplication - Deletion - Primitive functions This is not about the primitive functions. It is about the structural transformations and how they can be expressed as function composition, because that exposes the chain rule. This is what the CCC transformation is about: exposing composition. So if the solution is going to be the chain rule, what does + mean? Let's watch Conal's lecture again. The paper above is a little too dense for me atm... There really must be a simpler way. A difference of two trees is a list set of changes, where a change is a tag (add,remove,update), a path and a subtree or leaf. The derivative of a function on trees is then a function on the difference setls. The trick is maybe to see the trees as functions also? Let's concentrate on the paper now. Definition of D(u) where u is a function. D(x) = dx (change of x) Let's "fix" the paper to use a pure functional algorithm. There are no "changes", there are only linear functions. The derivative of a linear function is the linear function, which is the termination point of the recursion. This also solves the type error https://www.youtube.com/watch?v=vzLK_xE9Zy8 So the rules, boiled down, are: - abs: D( \x -> t ) -> \(x,dx) -> D(t) - app: D( s t ) -> D(s) (t, D(t)) for a concrete function, e.g. a projection of a tree into a value (e.g. a pattern matching primitive: f(#{a => A}) -> A. ... Conclusion for now: there is quite a bit of overhead in building up the primitives. In the practical cases I've seen it seems much simpler to map model changes to view changes explicitly without trying to derive them. Double work (initial render + diff), but not too bad in case the changes are not too extensive.