Elm vs. Bacon.js

2,889 views
Skip to first unread message

Samswell Pedersen

unread,
Apr 7, 2013, 11:54:19 PM4/7/13
to elm-d...@googlegroups.com
I am very interested in any opinions, comparison, or experience, with these two. I realize that Elm is a full functional language with static types & FRP, while bacon.js is a library written in Javascript (actually in Coffeescript, it seems) to bring FRP to Javascript (Coffeescript).

Is the goal for Elm to increasingly offer its own functional & compositional flavors of things like CSS? 2D-graphics? 3D? Its own functional alternatives to Javascript libraries?

Anyone opinions on shortcomings of Bacon.js relative to Elm to allow easier building of good UIs? Animations?

Thanks!

dy...@techtangents.com

unread,
Apr 8, 2013, 12:50:16 AM4/8/13
to elm-d...@googlegroups.com
You could also compare:

- Rx.js (https://github.com/Reactive-Extensions/RxJS)
This is the well-known Microsoft FRP library that Erik Meijer is involved in.

- FlapJax (http://www.flapjax-lang.org/)
Flapjax came to the js FRP scene really early - it was the first one I heard of. It can be used as a language or a js library. I think the language does automatic lifting, but the library doesn't.

- Processing (http://processingjs.org/)
Processing is an FRP language with automatic lifting, though I'm not sure that the language designers are aware of this fact. I think John Resig was involved in the js version of it.

- Haste (https://github.com/valderman/haste-compiler)
Haste is a Haskell-to-JS compiler, like Fay. It has an FRP library. I think Haste uses Cabal for managing code in different libraries - cabal has some nice flags that let you plug in the compiler. I'd like to port this ability to Fay and maybe Elm.

Also, I found this: a bacon.js demonstration in Fay:
https://github.com/NicolasT/Bacon-n-Fay

As an aside, even my brief comparison highlights that FRP is baked into Elm - like Processing and FlapJax, whereas Haste implements FRP as a library. I think language vs library is an interesting topic - my preferences are to keep languages minimal and define as much as possible in libraries. This pushes the language to be flexible enough to support powerful libraries, and by not have anything built-in, it allows the language to be more general purpose. But, Elm's goal is special-purpose and I suppose there might be some efficiencies in baking everything in. Food for thought. On another thread perhaps :)

Cheers!
> --
> You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

John Mayer (gmail)

unread,
Apr 8, 2013, 8:02:46 AM4/8/13
to elm-d...@googlegroups.com
So there are two orthogonal goals of Elm. The first is to bring modern FP language features to the web. The second is to design a set of core libraries that make building pages more pleasant. So I think, yes, Elm does have it's own "flavor" for some of these tasks.

Check out the Element type and the flow function for how Elm does positioning. Check out Form and collage for 2D graphics. Someday there will probably be a functional reactive 3D interface (Model and scene, perhaps) with a WebGL implementation.

I have a hunch that any FRP Javascript library will suffer from a lack of static typing, making me the programmer less confident about the compositions and abstractions that I'm trying to design.

Sent from my iPhone
--

Evan Czaplicki

unread,
Apr 8, 2013, 2:19:41 PM4/8/13
to elm-d...@googlegroups.com
Bacon also uses the "classical FRP" model which splits out Events and Behaviors (or whatever Bacon calls them). All of imperative FRP frameworks/libraries/etc I know of use this model. Later research showed that you can unify these ideas into just Behaviors (now called Signals) which I think is cool and is how things work in Elm.

I think the big thing is that Bacon can be added into an existing project pretty easily. This is going to be easier in Elm in the next release (0.8), but not on the level of mixing Elm directly with jQuery or something like that. So backwards compatibility is nice, but I think it dilutes the key benefits of FRP pretty quickly.

So with Bacon, you can still use CSS, other JS libraries, and all of that. My goal is to have an FFI to use that stuff if absolutely necessary, but my focus would be to grow an ecosystem of type-safe, functional libraries for these sorts of things.

For graphics, Elm is already pretty close to matching the expressiveness of CSS+canvas+svg+DOM. In terms of expressiveness, I can't think of anything serious that is missing in 0.8 for graphics. The runtime and compiler are not yet clever enough to use hardware acceleration though (as CSS does). In other words, Elm will grow into these areas and approach them in a functional way.

Jake Verbaten

unread,
Apr 8, 2013, 2:24:16 PM4/8/13
to elm-d...@googlegroups.com
Can you reference the later research that shows you can unify these ideas. For example I can't understand when `lift2` would be meaningful on two `Event`s

Evan Czaplicki

unread,
Apr 8, 2013, 2:33:37 PM4/8/13
to elm-d...@googlegroups.com
See page six of my thesis. It also provides references for this stuff.

If you wanted to emulate that exactly, I think you could do the following:

none _ = Nothing
asEvents signal = merge (Just <~ signal) (none <~ delay 0 signal)

Jake Verbaten

unread,
Apr 8, 2013, 2:43:07 PM4/8/13
to elm-d...@googlegroups.com
so in that case if you use lift2 on two events you should do an if check on both arguments to see whether it's an event or a Nothing ?

Do you wrap the signal returned by the input pool / button pool in this function ?

Evan Czaplicki

unread,
Apr 8, 2013, 3:16:39 PM4/8/13
to elm-d...@googlegroups.com
You can choose whatever interpretation you'd like for a signal, and if you choose that it represents an "event", I think you would just not use liftN. A pure function applied to events is not super interesting since the user will not have eyes quick enough to observe when an "event" comes through.

If you are doing things with "events", I think you are always going to want to use foldp. Also, `merge` is much more useful for "event"-like things.

Jake Verbaten

unread,
Apr 8, 2013, 3:20:15 PM4/8/13
to elm-d...@googlegroups.com
 I think you would just not use liftN. 

This is important.

I think you are always going to want to use foldp. Also, `merge` is much more useful for "event"-like things.

This is also important.

The primitives foldp and merges make a lot more sense for events.

The primitives lift2 and lift3 make a lot more sense for behaviors.

Sure you can use the singular term "signal" to represent both those ideas BUT for a user of Elm that has not read your thesis it's confusing that higher order signal functions (foldp, lift2, merges) don't uniformly make sense on all signals.

Evan Czaplicki

unread,
Apr 8, 2013, 3:58:58 PM4/8/13
to elm-d...@googlegroups.com
I'd recommend this mindset: "A signal is a value that changes discretely and always has a latest value. There are a number of things you can do with values that change discretely."

If you can think of a pair of APIs for Behavior and Event that is clearer, easier, and equally expressive when compared to the Signal library, please show me the API and compare with code when it is better than the current way. Since these ideas can be represented with signals, it is even possible to implement and use such an API right now.

My research and personal opinions have led me to think that Behavior/Event is not the way to go in the core language. Since 2001 when the isomorphism between Events and Behaviors was introduced, all of the research I know of uses signals. Perhaps they are all wrong, but I have not seen strong evidence for this.

Jake Verbaten

unread,
Apr 8, 2013, 4:52:09 PM4/8/13
to elm-d...@googlegroups.com
I think your existing set of functions is good. Maybe restricting some of them to only work on Signal's or Event's helps.

I have seen other FRP code where things are prefixed / postfixed with `E` and `B` and that is horribly confusing / frustrating.

I'm working on a signal library so I may try to aggressively seperate these things myself and see where that leads me.

Evan Czaplicki

unread,
Apr 8, 2013, 5:51:35 PM4/8/13
to elm-d...@googlegroups.com
Yeah, the accumB, accumE, rpSwitchB, etc. can be pretty off-putting :)

I think it could potentially be nice to be more restrictive about how a signal is interpreted in some cases, so let me know the results! I am very curious :)

de...@dsouzaville.com

unread,
Apr 8, 2013, 8:21:54 PM4/8/13
to elm-d...@googlegroups.com
On Monday, April 8, 2013 2:58:58 PM UTC-5, Evan wrote:
I'd recommend this mindset: "A signal is a value that changes discretely and always has a latest value. There are a number of things you can do with values that change discretely."

Would the latest value of a MouseClick signal be the most recent mouse click event?

If you can think of a pair of APIs for Behavior and Event that is clearer, easier, and equally expressive when compared to the Signal library, please show me the API and compare with code when it is better than the current way. Since these ideas can be represented with signals, it is even possible to implement and use such an API right now.

My research and personal opinions have led me to think that Behavior/Event is not the way to go in the core language. Since 2001 when the isomorphism between Events and Behaviors was introduced, all of the research I know of uses signals. Perhaps they are all wrong, but I have not seen strong evidence for this.

I'm hardly an expert, but the discussion here http://bit.ly/YHjni2 made sense and seems to match what you say: "To summarize: signals can be used for implementing FRP and are valuable for experimenting with new implementation techniques, but behaviors and events are a better abstraction for people who just want to use FRP."

Bacon uses the term "Property" instead of "Behavior"; it that works semantically, it is could be more approachable to non-FP types like me.
 

Evan Czaplicki

unread,
Apr 8, 2013, 9:37:02 PM4/8/13
to elm-d...@googlegroups.com
Would the latest value of a MouseClick signal be the most recent mouse click event?

I don't understand this question. See the mouse library.
 
I'm hardly an expert, but the discussion here http://bit.ly/YHjni2 made sense and seems to match what you say: "To summarize: signals can be used for implementing FRP and are valuable for experimenting with new implementation techniques, but behaviors and events are a better abstraction for people who just want to use FRP."

apfelmus wrote the reactive-banana library that uses Behaviors and Events. He seems skeptical of the newer research in FRP, particularly the arrowized FRP stuff. This is his core FRP library. I disagree with his claim about ease of use, and one of the goals of my thesis and the ~200 online examples to show that signals are pretty cool and pretty easy.

Jake Verbaten

unread,
Apr 8, 2013, 9:45:25 PM4/8/13
to elm-d...@googlegroups.com
He wants to say that the notion of a "current value" of  mouse.Clicks signal is dubious. It can either be `Unit` or `Nothing` depending on implementation details.


--

Evan Czaplicki

unread,
Apr 8, 2013, 9:53:59 PM4/8/13
to elm-d...@googlegroups.com
I have not yet felt like signals were weird for what I wanted to do. I see why you disagree. I only want to continue this discussion if it is driven by many examples that compare behavior/event and signals in a fair way.
--
Sent from Gmail Mobile

Evan Czaplicki

unread,
Apr 8, 2013, 9:56:05 PM4/8/13
to elm-d...@googlegroups.com
To clarify, I think decent sized examples are best because that's when you start having to mess with types to switch between behaviors and events.

Evan Czaplicki

unread,
Apr 8, 2013, 10:05:53 PM4/8/13
to elm-d...@googlegroups.com
Perhaps a key benefit is that events would not need a default value. I'll think about that more

Jake Verbaten

unread,
Apr 8, 2013, 11:49:04 PM4/8/13
to elm-d...@googlegroups.com
I like this section from that link:

"""
The argument for the distinction between behaviors and events is that their API is quite different. The main point is that they have different product types:

(Behavior a , Behavior b) = Behavior (a,b)
(Event a    , Event b   ) = Event (a :+: b)
"""

He's saying that the product of two behaviours is the `lift2` function and the product of two events is the `merge` function. This feels natural to me.

Also note that `merge(mousePosition, windowDimensions)` doesn't give you anything meaningful. I would have to think hard about how to merge two Behaviours into a coherent whole.

Perhaps a key benefit is that events would not need a default value. I'll think about that more

In my mind a "Behaviour" is a signal that has a coherent notion of default  value and current value that's not `Nothing`. and an "Event" is a signal that's doesn't have a notion of current state. 

Of course at best this is just bike shedding. Like I said I'll try to make a explicit distinction between the two in my signal library and see whether seperating the two makes the functions simpler and more restricted


de...@dsouzaville.com

unread,
Apr 9, 2013, 3:16:04 AM4/9/13
to elm-d...@googlegroups.com
Thanks, Jake. That is roughly what I meant to say. I cannot find a comfortable (even if informal) intuitive meaning for the concept of current value for mouse.isClicked, or for the "immediately after" explanation in the mouse library:
isClicked :: Signal Bool
True immediately after the left mouse-button has been clicked, and false otherwise.

de...@dsouzaville.com

unread,
Apr 11, 2013, 10:49:31 PM4/11/13
to elm-d...@googlegroups.com
Thanks, Evan. Elm looks lovely, but the prospect of being a somewhat "closed" ecosystem is a bit worrying. Could you share what kinds of things the 0.8 FFI interface will enable, even if in incomplete or draft form?

Related question: the current web pages generated from Elm seem to have style attributes defined on every DOM node, and updated dynamically on things like window resize, with no sharing via CSS. If I understood this correctly, is this also the plan going forward, or do you envision Elm having a way to (compositionally) define shared style, which get mapped in some way to CSS? Also, are all these updates being done by Elm?

Last related question: do you plan for Elm to run in Node.js (now or anytime soon)?

Thanks!

Jake Verbaten

unread,
Apr 11, 2013, 10:53:25 PM4/11/13
to elm-d...@googlegroups.com
The Elm style FRP abstractions are not suitable to node.js. 

Using an infinite value over time abstraction for a stateless server is just asking for performance issues. If you really prefer the elm language over node you may want to somehow seperate elm from its signal, input & graphics components. However there is a severe danger in using Elm for node which is node is awesome because there are 30000 js modules in npm that solve most problems. I don't think Elm is designed to make interacting with npm modules trivial so you'll have problems there.

If you find a good Signal abstraction for doing servers and database drivers then hit me up! I would love to know what you can find.

de...@dsouzaville.com

unread,
Apr 11, 2013, 10:58:10 PM4/11/13
to elm-d...@googlegroups.com
The Node.js question, rephrased: do you see Elm-generated Javascript for server-side functions running on Node.js at some point?

dy...@techtangents.com

unread,
Apr 11, 2013, 11:03:19 PM4/11/13
to elm-d...@googlegroups.com
I would like to run Elm code outside of a browser (e.g. in Node.js) for unit testing my non-FRP code modules without a browser.

Evan Czaplicki

unread,
Apr 12, 2013, 1:37:33 AM4/12/13
to elm-d...@googlegroups.com
A description of how Elm.init works can be found here. Let me know if you'd like clarifications or have suggestions. It is still easy to change it to mix with the the style of callbacks more nicely. This is mostly possible already, it just has a nicer API in 0.8.

This API will make it pretty easy to call out to Elm to do event processing. The paper Parallel FRP provides concrete ideas on how to specialize FRP for servers, focusing on efficiency through parallelization. It appears that there are no fundamental problems, and FRP could actually be a pretty nice fit. This is a longer-term idea for Elm.

It should also be possible to call Elm functions directly from JS, but I have not designed anything for this. I don't want to needlessly expose implementation details, so this would need to be done with care. It is totally possible though, it's all just JS functions.

I don't really understand the CSS question. Is this a question about performance or integration? Also, all of the rendering happens automatically in the Elm runtime. It manages the css tags.

Jake is working on a JS derivative of Elm that makes exactly the design choices he described. Jake, I tend to get a odd/negative vibe from you on the lists, like you are mainly into jumping on weaknesses without providing constructive info to people. I see where you are coming from with your comment above, but please be cool on the lists and please stop soliciting us to design your API for you. I have already outlined some ideas for you, and Elm is a ways off from focusing on that kind of question.

Jake Verbaten

unread,
Apr 12, 2013, 3:25:49 AM4/12/13
to elm-d...@googlegroups.com
It's not negativity. It's just that bringing all of the node core libraries into a pure & typed language like Elm sounds like a difficult task. I'm not being negative, I'm being blunt and realistic. Now of course you can do server-side FRP, it just won't be node.js. I don't mean to solicitice people into solving my problems for me.

For the purposes of browserless testing I'm sure you can get Elm running under node. 

Evan Czaplicki

unread,
Apr 12, 2013, 3:34:42 AM4/12/13
to elm-d...@googlegroups.com
Okay, sorry for reacting that way. I agree with what you: integrating directly with untyped libraries will definitely cause some friction, perhaps being unfeasible depending upon how egregiously untyped the API happens to be. I suspect they could be wrapped up nicely in an Elm module or called via the FFI, but using them directly in Elm would most likely be a no go.

Jake Verbaten

unread,
Apr 12, 2013, 3:47:12 AM4/12/13
to elm-d...@googlegroups.com
Ok evan has a point, it wouldnt be that hard to write a bunch of wrappers for some of node core's modules. 

Paweł Cesar Sanjuan Szklarz

unread,
Apr 12, 2013, 4:54:40 AM4/12/13
to elm-d...@googlegroups.com
Hi.

On a commercial project we are preparing several small prototypes to select the best set of technologies for the development process. We already know that some FRP approach is necessary because we will have complex dynamic behavior. Bacon.js and Elm are strong candidates.

Bacon.js works and integration with other libraries is relatively simple. For this prototype we build a backbone models and views, and create EventsStreams from backbone events. So input to the FRP machine is provided by an abstract model independent to the page DOM. The output (stream.onValue(..) on bacon.js) are updates to the backbone model, and this changes on model triggers change on the views.
Thanks to this separation, not all team members need to know about FRP. A team member 'can' learn about FRP, but does not 'have to'. For new members this is great, because they are productive already on the first day of work on the more standard part of the project.
Also testing is simple. We simulate events on the backbone model, and check that output of the FRP machine is correct. We use Qunit for this and execute the tests on the CI server using Rhino after each commit.   

We would like to use Elm, because the Signal model seems to be much better. Also the type system is important. The main problem is that this is a 1-0 selection: all in Elm or nothing.
I understand that Elm provide all necessary tools to make the job and the final result will be much better. The issue is that there is not enough skilled persons to setup the team.
Testing is also crucial, and on pure Elm it may be necessary to build some custom testing library.

Note that selection of a final tools is not only related to power of expression. In our case, testing and fast introduction for new members is really important.

I am trying to use foreign export/import to integrate backbone model with a Elm program. I don't need any html output from Elm, just updates to the abstract model. I will share any progress on this.

Regards.
Pawel Cesar Sanjuan Szklarz.
 

de...@dsouzaville.com

unread,
Apr 12, 2013, 11:54:41 AM4/12/13
to elm-d...@googlegroups.com


On Friday, April 12, 2013 12:37:33 AM UTC-5, Evan wrote:

I don't really understand the CSS question. Is this a question about performance or integration?

Both, I think, but my understanding is still quite incomplete. Suppose I take this page:
   http://elm-lang.org/examples/Basic.elm
itself as an example of Elm HTML and styling. Using Chrome dev-tools, I did not see much applicable CSS that uses class or other selectors. Instead, every DOM node seems to have things like padding, margin, width, height, position. Doesn't this mean that Elm's rendering logic is going up against tons of browser optimization of CSS-based rendering, layout, box-model, flow, etc? See below.

 
Also, all of the rendering happens automatically in the Elm runtime. It manages the css tags.

So let's try to make the same page narrow. Beyond a point, the text gets garbled & words overlay each other. This is not how I would expect the browser's rendering to work if it was fed reasonable HTML and CSS.

If these are valid concerns, the cause (& perhaps partial solution) might be in how you currently go from the data :
  reactive = addFolder "Reactive/"
      [ ("Mouse",  [ ("Position", "Position") ....

to Text, flow, etc.; and from those through to the generated HTML. Rather than making a bunch of disconnected Texts, flows, spacers, etc., could we think of it more as:

   make_a_repeated_block
         some_shared_styling_for_every_element_in_block
         the_list_of_elements_to_map

i.e. Elm could have a first-class notion of Style, and ways to compose styles, separate from the elements being styled. A Style could map in some way to a CSS style. Does it have this? To compose some style attributes like borders and spacings, this will need something comparable to the W3C box-model (perhaps Elm has this part already).

Reply all
Reply to author
Forward
0 new messages