3 ms·
A simple counter that can be manipulated with two buttons "Up" or "Down": https://github.com/HeinrichApfelmus/reactive-banana/blob/master/reactive-banana-wx/src
by cousin_it 15y ago
A simple counter that can be manipulated with two buttons "Up" or "Down": https://github.com/HeinrichApfelmus/reactive-banana/blob/master/reactive-banana-wx/src/Counter.hs https://github.com/HeinrichApfelmus/reactive-banana/blob/mas...
main = start $ do
f <- frame [text := "Counter"]
bup <- button f [text := "Up"]
bdown <- button f [text := "Down"]
output <- staticText f []
set f [layout := margin 10 $
column 5 [widget bup, widget bdown, widget output]]
network <- compile $ do
eup <- event0 bup command
edown <- event0 bdown command
let
counter :: Discrete Int
counter = accumD 0 $ ((+1) <$ eup) `union` (subtract 1 <$ edown)
sink output [text :== show <$> counter]
actuate network
This doesn't look like good UI code to me. It seems to use too many advanced FP concepts that have nothing to do with the task at hand. Are you sure this is better than the OO approach? Why?
- danieldk 15y agoThis doesn't look like good UI code to me. It replaces a mutable counter (that could potentially be changed anywhere in the program) by a definition of the counter that describes all possible changes it can have during its lifetime: counter = accumD 0 $ ((+1) <$ eup) `union` (subtract 1 <$ edown) So, we have a counter that has an initial value of one. Over time, 1 can be added and 1 can be subtracted, namely when repsectively an eup or edown event occurs. Being able to capture all possible 'state mutations' of a value in one assignment is good. It seems to use too many advanced FP concepts that have nothing to do with the task at hand. Which is a bit ironic, since the widgets are created in the IO monad with the 'do'-notation, which simulates imperative programming in Haskell :). A user interface should be designed with a WYSIWYG interface (Glade, Qt Designer) anyway, but that's besides the point.
- deleted 15y ago[deleted]
- cousin_it 15y ago> Being able to capture all possible 'state mutations' of a value in one assignment is good. I think there's a duality here. If there are 20 buttons, each of which can affect some of 30 counters, then the Haskell code would say "this counter is affected by these buttons", while imperative/OO code would say "this button affects these counters". It's not obvious to me that the former way of organizing code is better.
- danieldk 15y agoYou are still missing the point. In imperative programming there is no guarantee that the counter isn't modified in some place else or wrongly. In the end it's just an integer that allows all kinds of mutations. The possible value changes in the Haskell FRP example, on the other hand, are completely described. There is no other manner in which the value can change.
- cousin_it 15y agoOOP also has a way to guarantee that the counter can only be changed by calls from specific parts of the code, it's called encapsulation. For example, the counter could be an object that subscribes to button events, and the counter's value could be a private member variable of that object. What exactly is the win from FP here?
- dminor 15y agoI don't know Haskell but it appears this code is just setting up a few GUI elements and defining two events and their effects. What does good UI code look like?
- JadeNB 15y agoAside from, possibly, the monadic notation—which is just that, a notation, an artefact of the implementation rather than of the idea—what are the advanced FP concepts here?