Pros:
* Compile speed is mindblowing. As in, a big project compiles within a few seconds, and incremental compiles are instantaneous. The productivity gains of this cannot be overstated; you just don't get those moments anymore when you're waiting for webpack, your mind wanders off, lets just check HN real quick, ... no, you just stay in the flow. It's great. Elm, on the other hand, is sloooow.
* Type inference works really well. 9/10 times I don't even need to annotate anything and the compiler just knows. The only runtime errors I've ever run into were related to JS externals; the peace of mind knowing "if it compiles, it really works" is a game-changer even compared to TS.
* Error messages are (for the most part) fantastic and really helpful.
* Editor integration is solid, if a bit painful to set up at times.
* The ability to drop in the occasional chunk of dirty `[%bs.raw {...}]` is nice, and a clear advantage over Elm.
Cons:
* JSX support is a joke. You have to wrap every string in `(ReasonReact.String("bla"))`. You have to wrap arrays in `(ReasonReact.array(...))`. Passing children to components is supposed to be easy but will make you rip your hair out for sure. Etc., etc. But I'm sure it'll get there eventually.
* Refmt (the autoformatter) works pretty well but has lots of rough edges still. For instance, it removes all empty lines.
* State management isn't the greatest. Passing down props works alright but often it's just easier to keep things in a central Redux-ish store, especially because every. little. thing. needs to be passed down explicitly for the type checker to work.
* shouldComponentUpdate is hard-coded to `true` right now; there is no shallow comparison by default so everything always re-renders. Will be fixed medium- to long-term, I've been told. Workarounds exist but are pretty gnarly. Elm is much better at this.
* The standard library is a mess. ReasonML has its own, but forget about it; you'll fall back on Belt (the BuckleScript one), which 8/10 times has what you need but then is split into "Belt" parts and "Js" parts for unknown reasons and isn't always complete (e.g. I constantly need to convert from lists to arrays and back, because some utility functions only exist for one of the two, also for no real reason). There is piping syntax (|> and |.) but it's never clear which one to use; sometimes the data goes in first, sometimes it goes in last. You get used to it eventually, but Elm is a land of milk and honey in comparison.
* Lack of sugar: For instance, you'll end up making heavy use of option types, which are great obviously. Unfortunately there's no easy access syntax, so you end up with deeper and deeper levels of nested `Js.Option.getWithDefault()` and/or pattern matching.
* Documentation is meh overall. ReasonML is well documented, but it's only a very thin layer on top of BuckleScript. It took me hours of trial and error to figure out JS interop in practice, setting up "comparators" just to create a `set(int)` etc. You're effectively required to grok all of JS, Reason, Bucklescript, and OCaml at once, and draw from all of them to piece together your code. I think this will take another year or two to iron out.
Overall, I haven't found an option yet that truly works well. Elm is beautiful but slow and will drown you in boilerplate. ReasonML is fast and mighty but the UX isn't there yet. React+Redux+Typescript+Babel+Webpack have everything you need but it's a pain to set up and maintain, it's slow, and you can never trust it 100%.
(Edit: I should note that both Elm and ReasonML have amazing communities with very active, friendly and responsive dev teams that really and truly want the best for their languages. I have huge respect for both and I would encourage anyone to give them a try, just don't expect a perfectly polished experience yet.)