From HaskellWiki
Jump to navigation Jump to search


Example of tangible programming in Eros

Eros enables higher-order functional programming via a visual, non-syntactic interface. Every component (basic value or function) is presented as a GUI-style visualization. In the case of functions, the visualizations are interactive, allowing the user/author to explore the domain and see corresponding range values. A value (usually function) and its visualization together form what I call a "tangible value" or "TV".

Programming happens through "gestural composition" of TVs. A user selects compatibly-typed input and output widgets, typically in different GUIs. The result is a fusion of the two TVs and their underlying, containing all of the original inputs and outputs except for the connected input and output. Higher-order programming is fully supported.

One application I have in mind for Eros is to be a more powerful kind of Photoshop/GIMP-like tool. In Photoshop or the GIMP, programmers create filters and users apply filters to make images. With Eros, the user can just as easily create new filters, and indeed there is no distinction between filters and users except that "images" happens not to be parameterized. Thus, the artist becomes a tool-maker, not just a tool-user.

Please see the ICFP Eros paper and talk for a description.

Eros is built on top of several other libraries: TypeCompose, DeepArrow, DataDriven, Phooey, and TV.

The rest of this page describes how to run Eros. Warning: this is a very early release and not very polished. Please share questions and suggestions on the talk page.

Here's a Google tech talk about Eros.

Starting Eros

You'll need two files from the Eros distribution: the wxWidgets library (wxc-msw2.4.2-0.10.1.dll or perhaps a more recent version) and the Eros executable (eros.exe). Make sure they're in the same directory or that the wxWidgets DLL is on your search path. Run eros.exe.

The menus


The "Parts" menu contains several pre-built TVs (tangible values) in various categories. Choosing one will instantiate a TV in the composition space.


This menu lists some generic transformations (arrows), defined on the DeepArrow type class. When you select one, the type-compatible outputs in your visible TVs will highlight. You can left-click on a highlighted output to apply the transformation.

The same options are also available by right-clicking on a TV output. In that case, you'll only be offered the type-compatible transformations. Choosing one applies it.


This menu contains some small collections of TVs, useful for demonstration. I picked them to go with the ICFP talk. Choose a menu entry to instantiate a few TVs. For instance, "functions" instantiates some function-valued TVs.

TV options

Miscellaneous commands acting on the current/active TV (the one with window focus):

  • Close: close active TV
  • Recover parents: if one or both of a TV's parents are closed, this option will make them visible again. The parents are either (a) the TV to which a Tweak has been applied, or (b) the two TVs fused into a single TV.
  • Toggle hide parents on fusion: by default, tweaking & fusion make a new TV and keep the parent TV(s) around, making it clear that tweaking & fusion are non-destructive operations. It's often more convenient, though, to have tweaking & fusion replace (hide) the parents when generating a new TV. This menu item changes between hiding parents and not hiding parents when making a new TV. If you do hide parents (or close them), you can always get them back with the Recover parents option.
  • Window: not very helpful at this point, since all of the TVs are called "TV". For an obscure reason, this list even includes closed TVs.


Users make new TVs from old ones by "fusion", which is a gestural generalization of function application and composition. To begin fusion, right click on an input widget and choose "start fusion". The result is that all type-compatible outputs highlight. To complete fusion, left-click on a highlighted output, resulting in a new TV. This new TV contains all of the inputs & outputs of the two TVs except for the fused input & output. Its underlying value is a corresponding fusion of the values underlying the two source TVs. The two "parent" TVs will disappear or remain, depending on the "Toggle hide parents on fusion".

Temporary connection

You can also make a temporary connection between compatible input & output. Doing so causes values to flow from the output to the input (effectively taking over the input), without fusing the TVs. To start a temporary connection, right-click on an output and choose "start connection". Compatible inputs will highlight. When you move your mouse cursor over one of the highlighted inputs, that input will be fed by the chosen output. When you move the cursor out of the input, the connection is broken. You can make a more durable (but still temporary) connection by right-clicking on a highlighted input and choosing "complete/break connection". You can then move your mouse cursor outside of the input without breaking the connection. In particular, you can go back to the output's containing TV and interactively change the input(s), which will then affect the other TV. (You may have to move the input slowly in order to see the effect in the other TV. I don't know why that is. Probably because one TV's event handlers have priority over the others.) To break the connection, right-click on the input and again choose "complete/break connection". Or to fuse, choose "start fusion" in the input, and then left-click on the output.