ANN: Buster 0.99.1, a library for application orchestration that is not FRP

Read more about it on its webpage: http://vs.renci.org/jeff/buster Yes, it’s to solve a particular problem. And yes, this is a rough draft of an explanation of how it works. I’ve not even really solidified the vocabulary yet, but I have this module which couches a large, abstract, interactive (both with the user and the system), multicomponent application in terms of a bus, inputs, behaviours, and events. * Time is continuous and infinite. * An event is a static, discrete item associated with a particular time. * The bus is the discrete view of event in time at an instant. * A widget is an IO action that assigns events to a particular time based only upon sampling the outside world (other events and behaviours are irrelevant to it). e.g. a Gtk Button is a widget, a readable network socket is an widget, the mouse is an widget, the keyboard is an widget, a multitouch gesture engine is a widget. * A behaviour is a continuous item — it exists for the entire program and for all times — which maps events on the bus to other events on the bus. It is an IO action as well — where widgets only sample the outside world and are in a sense read only, behaviours encapsulate reading and writing.

Sounds vaguely like Grapefruit's circuits, but I could be very wrong...
The link you provided seems to be broken?
On Thu, Apr 2, 2009 at 3:05 PM, Jeff Heard
Read more about it on its webpage: http://vs.renci.org/jeff/buster
Yes, it’s to solve a particular problem. And yes, this is a rough draft of an explanation of how it works. I’ve not even really solidified the vocabulary yet, but I have this module which couches a large, abstract, interactive (both with the user and the system), multicomponent application in terms of a bus, inputs, behaviours, and events.
* Time is continuous and infinite. * An event is a static, discrete item associated with a particular time. * The bus is the discrete view of event in time at an instant. * A widget is an IO action that assigns events to a particular time based only upon sampling the outside world (other events and behaviours are irrelevant to it). e.g. a Gtk Button is a widget, a readable network socket is an widget, the mouse is an widget, the keyboard is an widget, a multitouch gesture engine is a widget. * A behaviour is a continuous item — it exists for the entire program and for all times — which maps events on the bus to other events on the bus. It is an IO action as well — where widgets only sample the outside world and are in a sense read only, behaviours encapsulate reading and writing. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

It's vis instead of vs:
http://vis.renci.org/jeff/buster/
2009/4/2 Peter Verswyvelen
Sounds vaguely like Grapefruit's circuits, but I could be very wrong... The link you provided seems to be broken? On Thu, Apr 2, 2009 at 3:05 PM, Jeff Heard
wrote: Read more about it on its webpage: http://vs.renci.org/jeff/buster
Yes, it’s to solve a particular problem. And yes, this is a rough draft of an explanation of how it works. I’ve not even really solidified the vocabulary yet, but I have this module which couches a large, abstract, interactive (both with the user and the system), multicomponent application in terms of a bus, inputs, behaviours, and events.
* Time is continuous and infinite. * An event is a static, discrete item associated with a particular time. * The bus is the discrete view of event in time at an instant. * A widget is an IO action that assigns events to a particular time based only upon sampling the outside world (other events and behaviours are irrelevant to it). e.g. a Gtk Button is a widget, a readable network socket is an widget, the mouse is an widget, the keyboard is an widget, a multitouch gesture engine is a widget. * A behaviour is a continuous item — it exists for the entire program and for all times — which maps events on the bus to other events on the bus. It is an IO action as well — where widgets only sample the outside world and are in a sense read only, behaviours encapsulate reading and writing. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Yes,sorry. vis, not vs. http://vis.renci.org/buster
It is a bit like grapefruit's circuits, but where Grapefruit circuits
describe the flow of events from place to place, Buster never does.
Events exist for all behaviours, to be selected by name, group, or
source. The other major difference is the |~| or "beside" operator,
which describes concurrent application of behaviours.
A last but somewhat minor thing is that the Event type is fairly
general, allowing for multiple data to be attached to a single event
and this data to be of many of the standard types (Int, String,
Double, ByteString, etc) as well as a user-defined type. Of course,
such an event type could be defined for other FRP frameworks as well.
-- Jeff
On Thu, Apr 2, 2009 at 9:53 AM, minh thu
It's vis instead of vs: http://vis.renci.org/jeff/buster/
2009/4/2 Peter Verswyvelen
: Sounds vaguely like Grapefruit's circuits, but I could be very wrong... The link you provided seems to be broken? On Thu, Apr 2, 2009 at 3:05 PM, Jeff Heard
wrote: Read more about it on its webpage: http://vs.renci.org/jeff/buster
Yes, it’s to solve a particular problem. And yes, this is a rough draft of an explanation of how it works. I’ve not even really solidified the vocabulary yet, but I have this module which couches a large, abstract, interactive (both with the user and the system), multicomponent application in terms of a bus, inputs, behaviours, and events.
* Time is continuous and infinite. * An event is a static, discrete item associated with a particular time. * The bus is the discrete view of event in time at an instant. * A widget is an IO action that assigns events to a particular time based only upon sampling the outside world (other events and behaviours are irrelevant to it). e.g. a Gtk Button is a widget, a readable network socket is an widget, the mouse is an widget, the keyboard is an widget, a multitouch gesture engine is a widget. * A behaviour is a continuous item — it exists for the entire program and for all times — which maps events on the bus to other events on the bus. It is an IO action as well — where widgets only sample the outside world and are in a sense read only, behaviours encapsulate reading and writing. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Check links... god. http://vis.renci.org/jeff/buster (can you tell
I was up till 3am last night?)
On Thu, Apr 2, 2009 at 10:05 AM, Jeff Heard
Yes,sorry. vis, not vs. http://vis.renci.org/buster
It is a bit like grapefruit's circuits, but where Grapefruit circuits describe the flow of events from place to place, Buster never does. Events exist for all behaviours, to be selected by name, group, or source. The other major difference is the |~| or "beside" operator, which describes concurrent application of behaviours.
A last but somewhat minor thing is that the Event type is fairly general, allowing for multiple data to be attached to a single event and this data to be of many of the standard types (Int, String, Double, ByteString, etc) as well as a user-defined type. Of course, such an event type could be defined for other FRP frameworks as well.
-- Jeff
On Thu, Apr 2, 2009 at 9:53 AM, minh thu
wrote: It's vis instead of vs: http://vis.renci.org/jeff/buster/
2009/4/2 Peter Verswyvelen
: Sounds vaguely like Grapefruit's circuits, but I could be very wrong... The link you provided seems to be broken? On Thu, Apr 2, 2009 at 3:05 PM, Jeff Heard
wrote: Read more about it on its webpage: http://vs.renci.org/jeff/buster
Yes, it’s to solve a particular problem. And yes, this is a rough draft of an explanation of how it works. I’ve not even really solidified the vocabulary yet, but I have this module which couches a large, abstract, interactive (both with the user and the system), multicomponent application in terms of a bus, inputs, behaviours, and events.
* Time is continuous and infinite. * An event is a static, discrete item associated with a particular time. * The bus is the discrete view of event in time at an instant. * A widget is an IO action that assigns events to a particular time based only upon sampling the outside world (other events and behaviours are irrelevant to it). e.g. a Gtk Button is a widget, a readable network socket is an widget, the mouse is an widget, the keyboard is an widget, a multitouch gesture engine is a widget. * A behaviour is a continuous item — it exists for the entire program and for all times — which maps events on the bus to other events on the bus. It is an IO action as well — where widgets only sample the outside world and are in a sense read only, behaviours encapsulate reading and writing. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Funny ... I never write an url in a mail : I type it in firefox (so I
actually check it) then copy/paste it.
2009/4/2 Jeff Heard
Check links... god. http://vis.renci.org/jeff/buster (can you tell I was up till 3am last night?)
On Thu, Apr 2, 2009 at 10:05 AM, Jeff Heard
wrote: Yes,sorry. vis, not vs. http://vis.renci.org/buster
It is a bit like grapefruit's circuits, but where Grapefruit circuits describe the flow of events from place to place, Buster never does. Events exist for all behaviours, to be selected by name, group, or source. The other major difference is the |~| or "beside" operator, which describes concurrent application of behaviours.
A last but somewhat minor thing is that the Event type is fairly general, allowing for multiple data to be attached to a single event and this data to be of many of the standard types (Int, String, Double, ByteString, etc) as well as a user-defined type. Of course, such an event type could be defined for other FRP frameworks as well.
-- Jeff
On Thu, Apr 2, 2009 at 9:53 AM, minh thu
wrote: It's vis instead of vs: http://vis.renci.org/jeff/buster/
2009/4/2 Peter Verswyvelen
: Sounds vaguely like Grapefruit's circuits, but I could be very wrong... The link you provided seems to be broken? On Thu, Apr 2, 2009 at 3:05 PM, Jeff Heard
wrote: Read more about it on its webpage: http://vs.renci.org/jeff/buster
Yes, it’s to solve a particular problem. And yes, this is a rough draft of an explanation of how it works. I’ve not even really solidified the vocabulary yet, but I have this module which couches a large, abstract, interactive (both with the user and the system), multicomponent application in terms of a bus, inputs, behaviours, and events.
* Time is continuous and infinite. * An event is a static, discrete item associated with a particular time. * The bus is the discrete view of event in time at an instant. * A widget is an IO action that assigns events to a particular time based only upon sampling the outside world (other events and behaviours are irrelevant to it). e.g. a Gtk Button is a widget, a readable network socket is an widget, the mouse is an widget, the keyboard is an widget, a multitouch gesture engine is a widget. * A behaviour is a continuous item — it exists for the entire program and for all times — which maps events on the bus to other events on the bus. It is an IO action as well — where widgets only sample the outside world and are in a sense read only, behaviours encapsulate reading and writing. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

It seems to be a trend to use more and more IO in new FRP approaches.
Grapefruit's circuits encapsulate side effects, as does your approach
This is a big departure from the "pure" libs like Fran, Yampa, Reactive, ...
I wander if this is because of some fundamental problem with functional
programming when it comes to FRP?
Some people claim that IO is also pure, and I tend to agree if we can
capture the state of the real world and rewind to it somehow :)
On Thu, Apr 2, 2009 at 4:06 PM, Jeff Heard
Check links... god. http://vis.renci.org/jeff/buster (can you tell I was up till 3am last night?)
On Thu, Apr 2, 2009 at 10:05 AM, Jeff Heard
wrote: Yes,sorry. vis, not vs. http://vis.renci.org/buster
It is a bit like grapefruit's circuits, but where Grapefruit circuits describe the flow of events from place to place, Buster never does. Events exist for all behaviours, to be selected by name, group, or source. The other major difference is the |~| or "beside" operator, which describes concurrent application of behaviours.
A last but somewhat minor thing is that the Event type is fairly general, allowing for multiple data to be attached to a single event and this data to be of many of the standard types (Int, String, Double, ByteString, etc) as well as a user-defined type. Of course, such an event type could be defined for other FRP frameworks as well.
-- Jeff
On Thu, Apr 2, 2009 at 9:53 AM, minh thu
wrote: It's vis instead of vs: http://vis.renci.org/jeff/buster/
2009/4/2 Peter Verswyvelen
: Sounds vaguely like Grapefruit's circuits, but I could be very wrong... The link you provided seems to be broken? On Thu, Apr 2, 2009 at 3:05 PM, Jeff Heard < jefferson.r.heard@gmail.com> wrote:
Read more about it on its webpage: http://vs.renci.org/jeff/buster
Yes, it’s to solve a particular problem. And yes, this is a rough draft of an explanation of how it works. I’ve not even really solidified the vocabulary yet, but I have this module which couches a large, abstract, interactive (both with the user and the system), multicomponent application in terms of a bus, inputs, behaviours, and events.
* Time is continuous and infinite. * An event is a static, discrete item associated with a particular time. * The bus is the discrete view of event in time at an instant. * A widget is an IO action that assigns events to a particular time based only upon sampling the outside world (other events and behaviours are irrelevant to it). e.g. a Gtk Button is a widget, a readable network socket is an widget, the mouse is an widget, the keyboard is an widget, a multitouch gesture engine is a widget. * A behaviour is a continuous item — it exists for the entire program and for all times — which maps events on the bus to other events on the bus. It is an IO action as well — where widgets only sample the outside world and are in a sense read only, behaviours encapsulate reading and writing. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Jeff Heard wrote:
A last but somewhat minor thing is that the Event type is fairly general, allowing for multiple data to be attached to a single event and this data to be of many of the standard types (Int, String, Double, ByteString, etc) as well as a user-defined type. Of course, such an event type could be defined for other FRP frameworks as well.
That sounds the opposite of general. That sounds specific. (Int, String, Double, ByteString as well as a user-defined type....). Can you explain the reason for the EDouble, EString (etc.) alternatives as opposed to making the event simply (parametrically) polymorphic in "a" ? Jules

It is parametrically polymorphic in a. And no, it's an arbitrary
decision, BUT... it allows me and other users to define generally
useful behaviours and widgets to package with the library using the
basic types without locking down 'a'. The EventData type looks like
this:
data Event a { ..., edata :: EData a, ... }
data EData a = EChar Char
| EString String
| EStringL [String]
| EByteString ByteString
| EByteStringL [ByteString]
| EInt Int
| EIntL [Int]
| EDouble Double
| EDoubleL [Double]
| EBool Bool
| EBoolL [Bool]
| EOther a
| EOtherL [a]
Now, given that arbitrary decision, I'd be willing to modify Event so
that it is parametric on 'a' without EData and include EData as an
"example" binding for 'a' if the user chooses to use it. However, I
foresee most behaviours and widgets that are "generally useful" to be
dependent on this type, which is why I made it a basic part of Event.
-- Jeff
On Thu, Apr 2, 2009 at 11:05 AM, Jules Bean
Jeff Heard wrote:
A last but somewhat minor thing is that the Event type is fairly general, allowing for multiple data to be attached to a single event and this data to be of many of the standard types (Int, String, Double, ByteString, etc) as well as a user-defined type. Of course, such an event type could be defined for other FRP frameworks as well.
That sounds the opposite of general. That sounds specific. (Int, String, Double, ByteString as well as a user-defined type....).
Can you explain the reason for the EDouble, EString (etc.) alternatives as opposed to making the event simply (parametrically) polymorphic in "a" ?
Jules

Jeff Heard wrote:
It is parametrically polymorphic in a. And no, it's an arbitrary decision, BUT... it allows me and other users to define generally useful behaviours and widgets to package with the library using the basic types without locking down 'a'. The EventData type looks like this:
data Event a { ..., edata :: EData a, ... }
data EData a = EChar Char | EString String | EStringL [String] | EByteString ByteString | EByteStringL [ByteString] | EInt Int | EIntL [Int] | EDouble Double | EDoubleL [Double] | EBool Bool | EBoolL [Bool] | EOther a | EOtherL [a]
Maybe I wasn't clear, and probably I'm being dense. I understand what you've done - I looked at the type declarations before commenting - but I don't understand why. Why is it useful to be able to use basic types without locking down 'a'? Why is it useful to have a value of type "Event FooBar" which, in apparent defiance of the FooBar parameter, actually contains a value of type Double? Jules

On Thu, Apr 2, 2009 at 11:22 AM, Jules Bean
Maybe I wasn't clear, and probably I'm being dense. I understand what you've done - I looked at the type declarations before commenting - but I don't understand why.
Why is it useful to be able to use basic types without locking down 'a'?
Why is it useful to have a value of type "Event FooBar" which, in apparent defiance of the FooBar parameter, actually contains a value of type Double?
Jules
I'm assuming everyone won't want to start from scratch in creating all their widgets and behaviours. A bus contains only events of type 'a', therefore all widgets and behaviours on that bus must use events of type 'a'. It is possible to run multiple buses at the same time in the same program, and even possible to have them communicate between each other (forkIO-ing the buses and attaching some arbitrary behaviour that takes events from bus0, translates their types and then puts them on bus1), and so that way you could use multiple types, but I don't see a problem with a user having to read the documentation and understand that an Event of type a contains data that is a variant including type a. How is it useful? Consider the following widgets: commandLineArgsWidget :: Widget a commandLineArgsWidget = getArgs >>= \args -> produce' "Environment" "CommandLineArgsWidget" "argv" Persistent [EStringL args] environmentWidget :: Widget a environmentWidget b = getEnvironment >>= mapM_ (\(k,v) -> produce' "Environment" "EnvironmentWidget" k Persistent [EString v] b) progNameWidget :: Widget a progNameWidget b = getProgName >>= \v -> produce' "Environment" "ProgramNameWidget" "ProgramName" Persistent [EString v] b As the library stands right now, I can take these widgets and put them in a module and include them as part of the Buster library, and they can be used pretty arbitrarily. I can see being more semantically pure and changing Event a to contain data of type a instead of data of type [EData a], in which case the type signatures would look like this: progNameWidget :: WIdget [EData a] and so forth to be compatible with Bus [EData a], but I think that in the end so many widgets will reuse the EData type that it's just as well to make it part of the Event rather than force the user to be explicit about it every time. But if I'm generally disagreed with about this, I can change it -- I'm pretty neutral about it, to be honest. -- Jeff

Alright, updated it to extract EData from the Event type and make it
separate. Basically, now all type signatures
Event a
Widget a
Behaviour a
should read
Event [EData a]
Widget [EData a]
Behaviour [EData a]
for backward compatibility.
On Thu, Apr 2, 2009 at 11:53 AM, Jeff Heard
On Thu, Apr 2, 2009 at 11:22 AM, Jules Bean
wrote: Maybe I wasn't clear, and probably I'm being dense. I understand what you've done - I looked at the type declarations before commenting - but I don't understand why.
Why is it useful to be able to use basic types without locking down 'a'?
Why is it useful to have a value of type "Event FooBar" which, in apparent defiance of the FooBar parameter, actually contains a value of type Double?
Jules
I'm assuming everyone won't want to start from scratch in creating all their widgets and behaviours. A bus contains only events of type 'a', therefore all widgets and behaviours on that bus must use events of type 'a'. It is possible to run multiple buses at the same time in the same program, and even possible to have them communicate between each other (forkIO-ing the buses and attaching some arbitrary behaviour that takes events from bus0, translates their types and then puts them on bus1), and so that way you could use multiple types, but I don't see a problem with a user having to read the documentation and understand that an Event of type a contains data that is a variant including type a. How is it useful? Consider the following widgets:
commandLineArgsWidget :: Widget a commandLineArgsWidget = getArgs >>= \args -> produce' "Environment" "CommandLineArgsWidget" "argv" Persistent [EStringL args]
environmentWidget :: Widget a environmentWidget b = getEnvironment >>= mapM_ (\(k,v) -> produce' "Environment" "EnvironmentWidget" k Persistent [EString v] b)
progNameWidget :: Widget a progNameWidget b = getProgName >>= \v -> produce' "Environment" "ProgramNameWidget" "ProgramName" Persistent [EString v] b
As the library stands right now, I can take these widgets and put them in a module and include them as part of the Buster library, and they can be used pretty arbitrarily. I can see being more semantically pure and changing Event a to contain data of type a instead of data of type [EData a], in which case the type signatures would look like this:
progNameWidget :: WIdget [EData a]
and so forth to be compatible with Bus [EData a], but I think that in the end so many widgets will reuse the EData type that it's just as well to make it part of the Event rather than force the user to be explicit about it every time. But if I'm generally disagreed with about this, I can change it -- I'm pretty neutral about it, to be honest.
-- Jeff

On Thu, Apr 02, 2009 at 11:53:00AM -0400, Jeff Heard wrote:
and so forth to be compatible with Bus [EData a], but I think that in the end so many widgets will reuse the EData type that it's just as well to make it part of the Event rather than force the user to be explicit about it every time. But if I'm generally disagreed with about this, I can change it -- I'm pretty neutral about it, to be honest.
Why not trying something like what was done with the new extensible extensions, using typeable existencials and casts? That way you could put any value you want and they would all be first class citizens. Another random idea: a phantom type could be used to be explicit about the type of event something produces or expects, something on the lines of
data EData a = forall b. Typeable b => EData b deriving (Typeable)
-- | Extract the data. extract :: EData a -> a extract (EData d) = case cast d of Just x -> x Nothing -> error "extract: phantom didn't match"
-- | Carefull extract the data, returns @Nothing@ if the phantom -- type doesn't match. extractM :: EData a -> Maybe a extractM (EData d) = cast d
-- | Extracts any type of data from a polymorphic 'EData'. extractAny :: (forall a. EData a) -> Maybe b extractAny (EData d) = cast d -- Is the forall above useful to prevent mistakes or not?
-- | Unsafely casts the phantom type to another one. unsafeCastData :: EData a -> EData b unsafeCastData (EData d) = EData d
Your examples would become something like
commandLineArgsWidget :: Widget [String] commandLineArgsWidget = getArgs >>= \args -> produce' "Environment" "CommandLineArgsWidget" "argv" Persistent args
environmentWidget :: Widget String environmentWidget b = getEnvironment >>= mapM_ (\(k,v) -> produce' "Environment" "EnvironmentWidget" k Persistent v b)
progNameWidget :: Widget String progNameWidget b = getProgName >>= \v -> produce' "Environment" "ProgramNameWidget" "ProgramName" Persistent v b
where I'm assuming that you could construct the EData inside produce' as now that's the only constructor available. The bus could then be polymorphic on the phantom type. Why use phantom types at all, then? It at least serves for documentation purposes. Well, it is a random idea after all :). -- Felipe.
participants (5)
-
Felipe Lessa
-
Jeff Heard
-
Jules Bean
-
minh thu
-
Peter Verswyvelen