
apfelmus wrote:
Brian Hulley schrieb:
main = do buffer <- createBuffer edit1 <- createEdit buffer edit2 <- createEdit buffer splitter <- createSplitter (wrapWidget edit1) (wrapWidget edit2) runMessageLoopWith splitter
... Thus the ability to abstract mutable state gives to my mind by far the best solution.
I'm not sure whether mutable state is the real goodie here. I think it's the ability to indpendently access parts of a compound state. In other words, the IORef created by buffer is a part of the total program state but you can access it independently. There is a functional idiom for that, see also
Sander Evers, Peter Achten, and Jan Kuper. "A Functional Programming Technique for Forms in Graphical User Interfaces". http://www.st.cs.ru.nl/papers/2005/eves2005-FFormsIFL04.pdf
Thanks for this reference. This is indeed a real key to the problem. (Though a possible downside with compositional references might be efficiency as the modified sub-state needs to be injected back into a new composite state but perhaps the solution here would be to have uniqueness typing as in Clean so that these injections could hopefully be erased at compile time.) I think one of the issues with Haskell is that there are so many features to choose from it is difficult to know how to approach a problem eg for streams you can have 1) A lazy list 2) A typeclass with get and pushBack methods 3) An object using an existential to wrap (2) 4) A record containing get and pushBack methods 5) A monad with get and pushBack actions 6) A simple function wrapped in a newtype: newtype Stream a = Stream (() -> Maybe (a, Stream a)) and I tend to only discover a simple solution like (6) (which works equally well for both strict and lazy languages) after spending an enormous amount of time on 1,2,3,4,5... ;-)
- For Graphics, I want to build a graphic from smaller ones and then draw it. I don't want to know how drawing is implemented and what mutable state might be involved. - For a GUI, I want to write down the data dependencies and a library converts this to a mesh of mutable state.
That's what I mean with "higher level functional model". I agree this would be ideal. A challenge I don't yet know how to solve, when dealing with 3d graphics, is that it seems that for efficiency it is necessary to consider a mesh of triangles to be an object with identity in order to be able to display an updated mesh (eg as the user drags a vertex with the mouse) in real time. This is because the representation of a mesh is constrained by the low level details of the graphics system eg vertices might need to be represented by a contiguous array of unboxed positions and normals, and triangles by a contiguous array of vertex indices, and it is too expensive to copy these arrays on each frame. Perhaps though this is another case where some form of uniqueness typing as in Clean could come to the rescue so one could write:
createMesh :: [Vertex] -> [[VertIndex]] -> Mesh moveVertex :: Vertex -> *Mesh -> *Mesh instead of createMesh :: [Vertex] -> [[VertIndex]] -> IO Mesh moveVertex :: Vertex -> Mesh -> IO () Best regards, Brian.