Hacker News new | past | comments | ask | show | jobs | submit login
ReasonML – React as first intended (imaginarycloud.com)
235 points by spking on May 24, 2018 | hide | past | favorite | 187 comments



Honest question: why would someone use this instead of React?

From my point of view, React solved a real problem. JS before React (at least old-skool, with jQuery & co.) was simply unmaintainable. It was often easier to thow old projects away and start anew than to maintain what inevitably became a tangled mess of callbacks and global variables. Not because of incompetency of developers (at least I hope so ;) but because there were no standard of encapsulation, separation of concerns and similar.

Why would someone who knows React want to switch to ReasonML?


The last ReactJS project I was working on ended up with libraries such as Ramda, ImmubtableJS, recompose, etc, in order to make the codebase more functional... We also switched to TypeScript for the type-system. While these libs improved the overall experience, it never came close to what you get from a proper functional language. I'm currently working on a frontend that uses ReasonReact and it feels much smoother.

> Honest question: why would someone use this instead of React?

The libraries I mentioned have __a_lot__ of stars on github, I'm sure many people using them, those might be better off with ReasonML.

I hope ReasonML will succeed and the ecosystem catches up. ReasonML is the fucntional general purpose language I always wanted. If they get the concurrency story right it might become a nice functional alternative to Golang as well.


fucntional


ReasonML has more potential. Aside from its excellent type system (one of the best), it can also compile to native code. This has several benefits:

- Frontend: Your tools are fast. The ReasonML-to-JS compiler is already an order of magnitude faster that TypeScript, etc. Fastpack is a native bundler in the works that aims to bundle your project in under a second (and faster for incremental builds).

- Mobile & Desktop: Some are experimenting right now with writing a version of React in pure Reason that compiles to native code, bypassing the JavaScript runtime entirely.

- Backend: You'll be able to use the Node.js ecosystem but compile certain modules to native code when you need critical performance.

Edit: I should add, the Node.js backend story is currently the least developed part of the ecosystem (I'm personally working on getting that up to speed).


Yeah. The OCaml compiler is just crazy fast. It's like Go, but with a super nice functional language. The compiler seems to be doing a heck of a lot of heavy-lifting in such a small amount of time. I'd be interested in a talk about how it manages that, if anyone knows of one.


A lot of the tooling speed comes from a couple places:

1. The compiler optimizations being applied to code - Things like GADT's are able to be allocated very efficiently - Can generate code that doesn't box at runtime (smash it into a pointer is done as well) - Pointers are word-aligned

2. The OCaml runtime - No JIT - No warmup - Can emit native code

3. The HM type system - Typecheckers for HM are really simple [1]

[1] https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_sy...

This simplicity + the features of the compiler combine to make the OCaml compiler very fast, and very easy to write one (some undergrad CS classes do), and developer-time tenable to make both happen.


This reminds me that all those points would apply to dartlang


Except for the speed argument. For AngularDart projects: the current compiler (ddc) takes minutes to warm up and since it keeps all assets in memory, is quite memory hungry as well. The new incremental build tools are much nicer to use (store assets on disk), and a lot faster after the first build, but still nowhere near sub-second.


I mean, why even use node for the backend?


Thanks (to the others too), that does sound good.


You wouldn't necessarily use ReasonML instead of React, you can use them together. You would use ReasonML instead of whatever Babel/es6/es7/typescript/whatever.

Here is the official React binding (or whatever you call it) for ReasonML: https://reasonml.github.io/reason-react/

Using this you would still be using React, just in a different language. But my understanding is that you would not be using redux (if you are now) because it doesn't make sense in a language like ReasonML.


> But my understanding is that you would not be using redux (if you are now) because it doesn't make sense in a language like ReasonML.

Why would using Redux not make sense? It's not like the problem of sharing state between components goes away with a functional language?


It's covered in the article:

"When using ReasonML, we don't need Redux anymore. ReactReason stateless components already come with the concept of a build in reducer, which is meant to take care of the problems Redux used to address."


Reducers are only one (and IMO the least important) part of using Redux with React; the other part is `connect`, which lets you pass global state directly into a deeply nested component without passing it all the way down the tree via props. Unless I'm mistaken, ReactReason doesn't offer an alternative to that.


Historically a single connected root has been frowned upon. I'm not so sure it should still be feared now that you can use PureComponents and FSCs the whole way down. ShouldComponentUpdate calls are cheap in pure-town.


For me, it's not a matter of performance, but rather of convenience. If I have a deeply nested component that needs to dispatch an action or access a part of the global state, I don't want to have to pass that all the way down through every other component in the hierarchy. The grandparent of a "Like" button shouldn't need to know the details of how it's implemented with regards to the global state, but it's forced to if you pass everything via props.


The newly official Context API might change things here, since it will be much easier to pass state down to grandchildren. I’ve not been keeping up to date with the plans for what react-redux will do with the new API yet, could be interesting.


Action creators always felt like and unnecessary abstraction to me. To avoid the aforementioned problem, I passed down a message library, or action object that has all of the actions on it, and dispatch. It's all I need!


Sure, action creators are "unnecessary" - you can always declare action objects and action types directly inline:

    this.props.dispatch({type : "INCREMENT"});
Nothing's ever _forced_ you to use action creators, or declare your type constants separately.

However, we encourage use of action creators as a good practice. See my blog post "Idiomatic Redux: Why Use Action Creators?" [0] for some reasons, as well as the related Redux FAQ entry [1].

[0] http://blog.isquaredsoftware.com/2016/10/idiomatic-redux-why...

[1] https://redux.js.org/faq/code-structure#why-should-i-use-act...


I respect your opinion but found each of the arguments contained within weak or easily countered.

> 1 ... put the logic for creating that action in one place

This isn't so simple. You end up duping the action in at minimum 1 AC (often many ACs), and onboard the complexity of an unnecessary function, plus importing and connecting that function all over your app. A UNIQUE_ACTION_CONSTANT is an easy refactor, unlike action creators, which can cause a cascade of changes when reworking component structures.

> 3 ... larger logic that goes into preparing the action object,

This justies a function, not necessarily an AC.

> 4 ... lets the action creator worry about how to handle things

Smart components are already aware of the state system by means of connect. Further, in AC aware apps, you have a whole swath of extra imports to manage, more connect calls to manage, and a binding API to consider, which sometimes requires patterns and team agreement on their own. dispatch + messages does away with all of that, and is shown to be simple/effective as popularized in Elm and Reason.

> 5 ... testing

Kinda. I'll meet ya half way here. But stubbing disptach and/or component methods is also very cheap, and super simple to reason about.

I say this all in the spirit of collaboration and productive debate :)


The new context API can probably help with that. Pass an object through context that contains the reducer state of a root level component (or a getState() or whatever), plus a dispatch function. Blam, Redux-equivalent without a separate library.


ReasonReact doesn't have Context, the API is unstable so they aren't binding to it.


The new API as of 16.3 is stable, so I suspect ReactReason will support it soon (if it doesn't already, by default).

https://reactjs.org/docs/context.html


Ah, that's great that it's finally settled. RR is on v15 in terms of what it has to support though, so no dice; main focus at the minute seems to be on dropping v15 support and migrating to v16, which cleans up some of the code (particularly w/r/t the async side), but that has to happen before they bind to the new API, so going to be a while.


I commented before reading the article, just going by memory of reading about this before. Perhaps I was wrong about it not making sense in the language, but more that it isn't necessary when using ReactReason because the concept is built into that binding.


Nobody mentioned the biggest reason. True functional programming coupled with type checking leads to more modular programs with significantly less bugs. I don't know about ReasonML, but a similar framework called ELM delivers Zero run time errors. Zero. Languages that eliminate entire classes of errors from type errors to run time errors should be the future evolution of programming languages. React+redux was only a small step in the right direction.


Well said. When we went from JavaScript to TypeScript we completely eliminated any errors we had associated with types. Then we turned on the noImplicitAny and strickNullChecks options and completely got rid of our 'x is not a function of y' and 'z is not defined' errors.


ReasonML is a language that transpiles to JS, not a view library so it's not gonna replace React. The more appropriate question is why someone use this for developing React app rather than using plain JS? The answer is IMO because React paradigm lent itself better with functional way of handling state like immutability and persistent data structures that's why ReasonML is more like a perfect match.


Because React is a very natural fit for a functional language of which JS really isn’t. Which is also why it is so lovely to use React from Clojurescript.


How's Clojurescript interop story? what always holds me from using these compile to JS langs is the fear that the gains you get from using a better/nicer language are completely destroyed by all the interop churn.


As someone who's done a bunch of interop in ReasonML & ClojureScript, ClojureScript interop blows ReasonML away (in terms of ease) at the language level.

The current problem with ClojureScript interop is the Google Closure compiler's support for stuff on npm. I switched our team to using shadow-cljs[0] and it solved all of those problems. Would highly recommend.

[0] http://shadow-cljs.org/


Ok thanks, I know this can be highly subjective but which do you prefer between the two (reason and cljs) and why?


I really like both languages. Like, a lot. They both tick all the boxes of:

1. Immutable by default (with sane escape hatches) 2. Fully qualified namespaces 3. Functional (with sane escape hatches) 4. Good interop with host platform

At the beginning of this year, my team started a green field project to replace our old system. I had the chance to steer us toward ReasonML or Clojure(Script), and we decided on Clojure.

The main reasons were:

1. The number and maturity of libraries for Clojure(Script) was much higher 2. Clojure's server-side story was much better, and we needed to write a ton of services as well as client-side code 3. The ecosystem, language & tooling was much more stable for Clojure back then

I think that ReasonML has a ton of great ideas, it just lacks maturity. I love the language itself, but I would not yet want to inflict it upon my team mates who have spent the last 10 years writing Java back-end services. Clojure(Script) ended up being a much better fit and I feel like I am just as productive, if not moreso, than when I was writing code in ReasonML.


What level of inter-opt? If you want to gradually convert from JS to clojurescript, it seemed like a huge amount of work.


Ah, hmm.

Using JS from CLJS is incredibly easy. Like I said, shadow-cljs solved all of our problems there.

Going the other way - using code written in CLJS in JS - is another matter. This is not well supported by the ecosystem. shadow-cljs has much, much better support for this than the standard ClojureScript/closure compiler, but it doesn't hold a candle to what BuckleScript does.

IME, doing a top-down transition - where you convert the top of your app to ClojureScript, that calls everything - works best. From the top, you work your way down into each feature.

ReasonML, on the other hand, works better from the bottom up. Typing your whole app is hard, so you start with some small feature that then you export to JS land (since that's so much easier with BuckleScript). From the bottom, you work your way into writing more and more features in ReasonML.


Clojure, on any platform (JVM, JS, .Net) has a fundamental language-level philosophy of easy interop with the host.


Clojurescript has very easy JS interopt (clj->js), (js->clj) plus easy ways to export external js library functions. There's been nothing I can't do in CLJS.


Someone who knows React can easily be using ReasonML. So to me, the question is, why not? You can get most of the features of ReasonML with 3rd party libs - TypeScript for type safety, Redux for state management, and Immutable. However, when I look at the build time comparison, I doubt you'd get something as fast with JavaScript, at least not today.


Typescript, Redux, and Immutable.js work together as a pretty compelling stack, but they involve a fair bit of boilerplate compared to Elm or ReasonML.

Elm provides type safety, immutable data structures, and state management in a very compact but readable way. In fact, Redux was strongly inspired by Elm's state management.

All of these stacks are perfectly acceptable choices, so it comes down to a matter of personal preference. I'd encourage everyone to spend some time with Elm and ReasonML. I find them to be productive and very enjoyable tools.


> compared to Elm or ReasonML

PureScript deserves a mention in this list as well. More full-featured and general purpose than Elm, cleaner design than ReasonML. Prolly the smallest community of the 3.


I played with PureScript a little. It has advanced type system that captures a lot of semantics of JS allowing easy interobility with JS ecosystem. But that comes with a huge price. With all those monads and monad transformers interacting with JS it is easy to end up with stateful mess. Surely, it will be typed and functional mess, but still it is hard to maintain with all state pieces spread through code hiding in lambdas.

With Elm the situation is very different. All your code is pure. The runtime hides the state management and the only way to interact with JS is via message passing. The end result is code that is extremely easy to follow, maintain and debug. Moreover, as Elm style and tooling discourages using lambda-style callbacks with opaque state, all state is very explicit and often just by looking at the state data structures, one often can grasp what the code is doing. It is almost like code follows from the data structures.


Elm is a lang and a FW in one. Very opinionated. Very batteries included.

PS is a lang. It compiles well to JS, but there is no friction against making it compile to native, apart from the time it takes to maintain that compiler backend.

On top of PS you may pick a FW. Some have React.js under the hood, some follow more closely The Elm Architecture.

Only with a FW, PS can be compared to Elm.


Elm is also a language. Surely it's libraries and runtime assume JS and DOM, but nothing prevents creating other ports of the language or creating alternative libraries.

And yes, Elm is opinionated. But that is a consequence of being very simple and pure functional language. As its typesystem does not support using monads or effects to model state with code similar in style to that in non-functional languages, one inevitably ends up with a runtime similar to Elm browser bindings in any Elm embedding.

Essentially Elm is opinionated because its pure functional style is the only style supported by the language with no escape hatches like the do blocks in Haskell or PureScript.


I love Purescript, but I'd be hesitant to recommend it to anyone without a Haskell background. There's a lot more to learn in Purescript, and I'd worry that it could discourage people who are new to the Haskell family of languages.

I'd advise starting with Elm to fall in love with the development experience and wonderful error messages, and graduating to Purescript when you need more power.


I like PureScript a whole lot. Something that ClojureScript and Reason seem to have on PureScript is really efficient persistent structures being the default, at least if I remember correctly. It's been a while, but I seem to recall PureScript giving me nice, functional syntax that under the hood did lots of native JS object / array copies.


Interesting. We covered ELM a few weeks ago: https://www.imaginarycloud.com/blog/elm-javascript-reinvente...


The jump from Typescript/Flow to ReasonML is as significant (or more so) than the jump from plain JavaScript to Typescript/Flow.


Facebook rewrote Messenger in Reason. Before they had hundreds of bugreports in a year. Afterwards? Less then ten.


Did they rewrite it using the old language too, as a control? :)


Is there some official analysis of this?


Note, the ReasonML rewrite refers to the Web version of Messenger only (at the time of this blog post):

https://reasonml.github.io/blog/2017/09/08/messenger-50-reas...


Everyone that works with F# and OCAML can confirm the trend I guess..


For the same/similar reasons, more or less. You get a great type system, merlin(a great analysis tool), faster compilation, all kinds of great compile time checks, and you can still use react.


Those are all good things, but they aren't really the same reason. Parent describes JQuery to React as spaghetti code -> reasonable code, whereas React to ReasonML sounds like reasonable code -> reasonable code (with better tooling).


Yeah, I agree but would say reasonable code -> slightly more maintainable, reasonable code. Sure, the low hanging fruit is gone, but it's a similar reason. What I'm getting at is that you can write spaghetti React pretty easily, and people do. One of the core promises of using an ML to do react is that its harder to mess with state all over the app and wind up with a big bowl of spaghetti.


JS code can be a pain to maintain (in the membrane... joke, sorry, I'll stop). And FB knows this. That's why they developed ReasonML: great JS interop, but much better maintenance story (than both JS and TS) because of the stronger typing discipline.

On a large code base, increased maintainability can be a huge commercial advantage.


Some developers believe (and prefer) in that good type systems help for large software projects.


A company like FB believes so too, judging from how much resources they throw at it.


> From my point of view, React solved a real problem. JS before React (at least old-skool, with jQuery & co.) was simply unmaintainable

Why would someone who knows Dojo or GWT want to switch to React?


(Caveat, we're adopting Elm and so I'm a little biased)

I think this article's conclusion of Reason being the enterprise grade and mainstream implementation of Elm, and Elm being a "prototype" is a little unfair to Elm.

Elm has developed a mature ecosystem in many ways, in a relatively short space of time, and two of the main reasons for that are the purity and the way the JS interop works. It explicitly shields the Elm world from issues in JS. This is one of the reasons we've decided to choose it. It is much more than a prototype, this was something that factored into our decision making process heavily.

I'm sure there are great things about Reason, but I can't help but feel that the impact will be limited because it doesn't take a stronger viewpoint.


Well Reason is really Ocaml, which has a much better type system than Elm (functors, open variants, a class system) , powerful meta programming (the react extension is just syntactic sugar around that) and is now backed by at least three large corporations (Facebook, Bloomberg and JaneStreet). It has a proven track record of handling large sophisticated projects and is not restricted to the web front end niche because it compiles to native code aswell. So you are able to write both the server and client code in the same language. The fact that reason has a dsl for react is just one of the killer arguments.


The type system might be more powerful, my point is more that if you can bypass it and integrate directly with JS, then people will, and then much of that value is lost. Elm doesn’t have that problem.


Not everyone has a greenfield project the fact that it integrates with JavaScript seamlessly and generates readable JavaScript is an advantage. They go as far as providing a plug-in for the standard JavaScript build flow, so you can basically start by just converting one file. On the other hand ocaml’s package manager (opam) and build system (jbuilder) are much better than elms equivalent and nothing is stopping you from using those for a greenfield project.


It lowers barrier to entry. You don't have - it's opt in. Not every project needs 100% type safety.

I would also love option to have gradual type friendliness because when prototyping I know my program is wrong in some different part, but I want to test given component in runtime, while I haven't refactored everything yet. I think having option like 'compileWithoutTypecheck' is very good for prototyping.


You can use `Debug.crash` in Elm, or `error` or `undefined` in Haskell to achieve this. They type check to anything, but will halt execution if reached.


You can type your JS bindings


Not to mention a real compiler for building executables as well, should that be of interest.


Just for the sake of completion, we covered ELM a few weeks ago: https://www.imaginarycloud.com/blog/elm-javascript-reinvente...


I'm reminded of the Hacker News post that introduced me to React from David Nolen back in 2013, where he first introduced ClojureScript's take on React, Om:

http://swannodette.github.io/2013/12/17/the-future-of-javasc...

Interested to take this for a spin.


Om isn't so much a take on React as it is a take on the state management layer and it uses React under the covers. I believe it's been largely superseded by re-frame [1], which follows the Redux / TEA model. There is an Om Next and that's basically a take on Falcor / Relay using the Datomic pull syntax but I haven't heard that much about it outside the talks where he was announcing it.

[1] https://github.com/Day8/re-frame/


Why doesn't Clojurescript eliminates the need for something like Redux where Reason does? as mentioned in the article.


IME using ClojureScript, you don't really need something like Redux/re-frame all that often either.

Once you've handled local state and remote data dependencies, you have like 10% of your app state left. That can easily be solved with a global atom (a la re-frame) or something like the new React context API.

Our understanding of how to handle state, remote data fetching, etc. has grown a lot over the last few years. Both the React & ClojureScript ecosystem went all-in on global state stores like Redux because, at the time, we thought we needed it. It felt like, if we needed a global state store for one thing, that it made more sense to just put everything in there for cohesiveness. It also was hard to determine up-front what was needed globally (mostly data IME) and what was only needed locally.

It turns out that local state and something like apollo/relay/"suspense" for remote data solve the 80-90% case, and now we're getting better tools like React context to handle the last 10%. I don't think that Redux/re-frame is going away, but the number of apps that I would implement with them has gone way down over the years.


> ClojureScript's take on React, Om

His take on React in ClojureScript would probably be a better qualifier, there have been others. Reagent is a popular alternative take on a cljs React interface.


Fulcro is a full-stack framework that's based on om.next. I've playing around with it for sometime and i feel that it makes the om.next query/mutation model much more easier to use and understand.

http://fulcro.fulcrologic.com/


I really want to use ReasonML in one of my next projects but I always come back to two main questions.

How much is it easy to use JS components like the Calendar of Airbnb for instance? And is it really easy to use BuckleScript? The "[%bs.raw ..." and others look hard to read/use. Is it the case or just a feeling?

Is there someone who already tried it enough to know the answers?


It's not any less convenient than React appears to be.

Disclaimer: I've only used it for small Todo project, I'm not a front end guy.

Disdisclaimer: I've not used React at all.

However, if you need really strong JS interop, consider something like F#'s Fable. F# is gaining a lot of momentum and now that SAFE stack is apparently Microsoft-blessed, I expect it to continue growing even more.


1k upvotes. I check in on Fable and F# semi frequently but SAFE has somehow slipped under my radar. I wonder if the ionide project will get some extra support..

Suave though... Nothing against Suave, but it's not the Phoenix competitor the ecosystem is in dire need of. I was under the impression some newer frameworks like Giraffe were going to fill that void..


It's in an early stage but the Saturn [1] project is aiming to compete with Phoenix more directly. The owner is a fairly prolific F# open source contributor and presented it at NYC F# last month but that's about all I know about it.

[1] https://github.com/SaturnFramework/Saturn


That's fantastic! I gave F# a look right after MS announced dotnet was being open source and have been excited for it's "arrival" ever since. The pieces seem to be coming together, albeit very slowly..

* "Official" Cross platform support -> dotnet core FTW!

* Cross-IDE intellisense support -> Ionide, Check!

* Dotnet core support -> Check, finally(and make sure to set Ionide to use core)!

* F# to javascript cross compilation project with some traction -> Fable, check(Fable needs serious documentation help though)!

* A great framework competing head on with Phoenix -> Hopefully soon :)

The potential just seems sooo massive. Hopefully it blows up quicker than Haskell ;)


I started looking at F# because of .NET Core, and I'm really liking it. I currently use Giraffe in a project, but I'll be switching it to Saturn soon (which uses Giraffe under the hood). And I've identified a potential use case for using Fable on some already written server-side code. Ionide is great, Neptune (F# debugger for VSCode) works well, and they both are maintained by the same person as Saturn.

Rider also works pretty well with F#, which is nice if you prefer the JetBrains IDEs.


Are you aware of https://github.com/SaturnFramework/Saturn

?

It's what the S in safe is actually meant to be, not suave. It's very similar, in heart anyways, to phoenix.

The fsharp community is fighting what is essentially an uphill battle. We have ML but we've got to jump through dotnet hoops to get shit done.

One man's cruft is another man's feature.

I doubt ionide will support SAFE, but maybe they will have a sister plugin? Idk how all that works.


So, I know this is a late reply to this but.. My reaction to the announcement post was "YES!", but I see a few choices in current "Moons" that are part of the same problem the project proposes to fix. Dapper is performant and good for what it is, but entity framework is an amazing ORM IMHO. Simple.Migrations does not have a CLI or support SQL generation?... These are too low level and don't really provide that flash OOTB experience IMHO; same critique(valid) made of Suave and Giraffe. To compete with rails and phoenix in velocity and user experience those technologies are going to have to be swapped out with more feature rich and ambitious libraries..


I had not! Looking into it now..

Ionide could just use some extra help I mean; it appears to be the work of just one guy. Hopefully with the increased interested in F# web development it will get some extra love more ala omnisharp.


I like F# and believe the author has done an amazing job evolving a functional language on the dot net platform but there are simply too many design choices in F# geared around C# compatibility and limitations of CLR being an object oriented language that when you switch to a different compilation target, these language aspects begin to look like bizarre warts.

Things like limitations on statically resolved type parameters being supported only for inline functions, etc. don't make sense for a language targeting javascript.

It is interesting to note that F# took a lot of concepts from OCaml but stripped out functors, structural typing support etc. to adapt to dotnet. These adaptations are largely required because Microsoft does not treat F# as a first class citizen (at the same level as C#) and CLR is very explicitly geared towards object oriented languages. An occasional endorsement from Microsoft does not magically obliviate these deeply ingrained design decisions in F#.

When targeting javascript these adaptions become really pointless. As demonstrated by Microsoft's own TypeScript language, Structural typing can be quite useful for interop.

It would be really nice if F# was a first class citizen in dotnet world and javascript was a first class compilation target maintained by the F# core team adapting the language to javascript target in the same way it currently adapts to dotnet. However that is not the present day reality. However typescript, despite being a javascript superset (and inheriting all its warts) has a really flexible type system and lends itself well to functional programming (as demonstrated by Giulio Canti's fp-ts [1] project).

Unlike ReasonML, however, typescript's type system is not sound. I have written a more detailed comparision [2] of TS and ReasonML. I do actively use TypeScript for my day job and mostly love it, but I am much more optimistic about ReasonML once the ecosystem matures.

tl;dr: The 80% best practices parity between ReasonML and modern functional javascript which the "What & Why" page of official documentation [3] talks about, does not exactly hold true for F#. So, while it is not that F# is not a great language, or that you can't build great apps with F#, however, as it currently stands, I don't see any compelling advantages of preferring F# over ReasonML, unless your backend is also F# and you want to (and can) share code between frontend and backend.

My familiarity with both F# and ReasonML is quite early stage (a few weeks each) and so would welcome any corrections.

---

[1] https://github.com/gcanti/fp-ts

[2] https://lorefnon.tech/2018/05/13/reasonml-vs-typescript-firs...

[3] https://reasonml.github.io/docs/en/what-and-why.html


If ocaml gets multicore finished before 20XX, do you think that f# developers who came from outside dotnet could be coaxed to ocaml?

Also, to just jump in what your comment was actually about, I think the prospect of writing f# is generally a more friendly experience for those using it for the web. Or especially those using azure. Getting started with f# with ionide and vscode is literally the most pleasant onboarding I've experienced since ruby. It just goes! Amazing.

But yeah, I think reason is great too. I really like that ocaml has a centralized, external package management story. Using paket+fake isn't like a bad experience, and I mean, I wrote scala for a couple years, I can always find gratitude for a build tool of its NOT sbt, but it's awkward at times and feels like a bit more work than it should be. Of course from Microsoft's perspective, being able to jump around dotnet libs is a major boon.

You do web development primarily? I've been eyeballing TS lately, you think that's probsbly a better choice for more professional work until reasonml gets bigger pants to wear?


> If ocaml gets multicore finished before 20XX, do you think that f# developers who came from outside dotnet could be coaxed to ocaml?

I do think that upcoming multicore support in OCaml is very exciting. I am more optimistic that it will attract people from Golang and C++. F# developers coming from outside dotnet is just too small a cohort.

> Getting started with f# with ionide and vscode is literally the most pleasant onboarding I've experienced since ruby.

Yeah, Ionide is really amazing. However merlin has also worked pretty well for me so far, and the emacs integration is a big plus for me. YMMV.

Also my comment was more around frontend use cases (compile to JS). I wouldn't be surprised if F# shines wrt Azure integration and within the dotnet ecosystem.

> You do web development primarily? I've been eyeballing TS lately, you think that's probsbly a better choice for more professional work until reasonml gets bigger pants to wear?

Yes, mostly node and frontend. In my area, professional work in reasonml is almost non-existent, but I do expect this to change in future.

As an developer coming from Ruby myself, glad to see more people from dynamic languages finding FP and type systems interesting.


I'm absolutely fascinated with type system theory. I also really like logic programming stuff too, some of what's happening in the relational logic world is very interesting stuff.

Anyways, thanks!


> If ocaml gets multicore finished before 20XX, do you think that f# developers who came from outside dotnet could be coaxed to ocaml?

Pfft. Run reasonml/ocaml on node, one event loop pr core, and use message passing for synchronisation / distributing work ;-)

I'm only half-joking.


Tangentially relevant: There is a serious and ambitious PR implemeting proper (web-worker style) threading support in Node.js core.

https://github.com/nodejs/node/pull/20876


I think we'd disagree about the relevance of this, but that IS exciting news! I'm very impressed overall with node progress, especially considering how unstable the ground seems to be, or have been, in jsverse.


> tl;dr: The 80% best practices parity between ReasonML and modern functional javascript which the "What & Why" page of official documentation [3] talks about, does not exactly hold true for F#.

The bulk of F# is functions acting on values modeled by types. This maps directly to JS. In the F# and .NET compatibility document[0], you'll note that all "core F#" components map directly to JS. And of course, you can consume JS libraries, TS definition files, etc. For example:

"The following F# semantic and syntactic features are also available:

* Records and Unions

* Structural Equality/Comparison

* Comprehensions (seq, array, list)

* Computation Expressions

* Pattern Matching

* Active Patterns

* Object Expressions

* Units of measure"

Do you have specific examples where F# semantics cannot map to JS such that the "80% rule" also does not hold?

[0]: fable.io/docs/compatibility.html


I am not at all contesting the value in the good parts of F#. It was my first foray into a functional language, and I was left seriously impressed.

> Do you have specific examples where F# semantics cannot map to JS such that the "80% rule" also does not hold?

Yes, my comment was around some of the C# compatibility things, which don't make sense when compiling to other targets.

> Tuples vs struct tuples distinction.

> Having both modules and namespaces

> Explicit interfaces

> The strange coupling of SRTP and inlining

I find OCaml's support for structural typing in classes and polymorphism to be more flexible than the above.

In typed FP, runtime reflection is seldom used, and I believe reflection support (and associated overhead) should have to be explicitly opted in.

I also faced weird issues when tracing the source of an exception in an async workflow, and some incomprehensible errors around automatic generalization. But this was a long time back and I no longer have the full context. These may have since been addressed.

My intent was certainly not to criticise F#. It has been developed and is used by people far smarter than me. It is just that after a preliminary evaluation I have not found a strong reason to prefer Fable over bucklescript in the absence of a more deeper commitment to dotnet stack.

I am also really fond of many modern JS features like Module <-> Filepath 1:1 correlation, explicit imports, ES6 proxies, tagged template literals (placeholders etc.) which TypeScript elegantly inherits from JS. Support for intersection types in typescrpt is also very handy.


The reason I found JS interop confusing in Bucklescript is there are multiple ways to do it, so it wasn't obvious which was the right way. I think a lot of that is due to the fact that Js is ultimately a very different language from OCaml, and so to get the two to work together there were quite a large number of different scenarios to cater for.

Once I got over that hump, it was all fairly simple.


Very easy to use components between JS react and ReasonML react. Docs describe this process well. As for the bucklescript macros, the most frequent ones are easy to get used to. bs.raw is a very last resort macro that is almost never used.

Highly recommend giving ReasonML a try.


bs.raw is actually really easy to use, but it's not encouraged since it's mostly a stepping stone to "real" bindings.

There is definitely a learning curve to JS bindings, but it pays off as you only have to learn them once.


ppx (like `[%bs.raw ...`) are indeed tricky. They mostly seem to be used around the FFI. My experience has been that if you're going to use JS components from within Reason, you just type the portions of the JS interface that you'll actually use, and that's pretty much always a subset.

When you're outside the FFI, the language really shines in build speed and output. Support of ES Modules out of the box is nice too.


If you’re willing to give up type safety it’s easy, it’s moderately harder if you want to stay in the type box


You could even use ReasonML without React, and build complex web apps, by going an even more Elm-like route with:

https://github.com/OvermindDL1/bucklescript-tea

Here some demo code (in ReasonML, not OCaml):

https://github.com/feluxe/bs-tea-starter-kit/blob/master/src...


I think ReasonML would see much faster adoption if they provided a stand-alone binary, or at least a pre-installed environment, which could be downloaded and installed as a whole.

ReasonML has a lot that makes it attractive to people that aren't already entirely invested in the JS/Node ecosystem, but doing the whole dance to make sure Node is installed correctly, and then using npm or yarn to install bucklescript and all the dependencies and make sure paths are correct, etc is a PITA, and a lot to ask of someone that's trying to evaluate whether it's worth incorporating in a new/existing project.

Provide a precompiled download with Node, npm/yarn, etc, and all the modules you need preinstalled, (just set the correct env vars to tell it to use it, such at PATH and some lib path) and you drastically reduce the overhead to not just trying it out, but actually using it.


As a masochist who has been willing to put up with the ecosystem pain of Clojure & ClojureScript for the love of the language, I can corroborate that it was a PITA to try ReasonML.

By the time I was done installing ReasonML to my machine, I was done trying Reason - ML and OCaml seem great, but I have limited mental resources and they are over-invested elsewhere.

This serves to inform future technology trials, because we don't assign enough nearly credence to the cost of trialling new things when we are already operating at our mental limits. By the time I am in a sufficiently quiet spot to try your thing, I'm probably exhausted after a long day of work. So make it as self-exemplary as possible. Steve Krug nailed it in "Don't Make Me Think." (https://www.sensible.com/dmmt.html)

I.e. What is the correct number of buttons to start/stop your microwave: one or two? The answer is zero: your food should already be warm.


Pardon me if I'm being dense here, but can't you just try out reasonML with a quick npm install from any platform? That's what they say in their "Quick Start" docs here: https://reasonml.github.io/docs/en/quickstart-javascript.htm...


IIRC from when I looked into it and got it working a few months back, you npm install bucklescript, wihch gives you a compiler to convert reason to JS, so to do any testing that actually includes a real world equivalent experience (such as include it in a sample webpage, maybe with React), you're talking about using webpack or something to bundle all the dependencies and steps into a deployment procedure.

Since it compiles to JS, and uses a JS lib and ecosystem to install the utilities that do the cross-compile, it's sort of like if to try out Python you had to first download and install a C compiler and C libraries used in Python, and compile python from scratch, just to try it out, because no pre-existing binaries, packages or installers existed. If that was the only way to try out Python (or Ruby, or Perl, or anything), you would get a lot less people trying it out, and a lot less willing to go through all that in their build chain (in case python updates, right?) if easier alternatives exist.

Just because your language compiles to another language, that doesn't mean to you get to ignore the on-boarding experience to that extent. At least not if you really want to succeed.


There's no ignoring going on. Reason exists on its own because it's not opinionated on what sort of app you're trying to build – frontend, backend, native, or some combination thereof.

If you're looking to build a web app with react (the subject of the article) then you can whip one up using one of their generators https://reasonml.github.io/reason-react/docs/en/installation...


> There's no ignoring going on. Reason exists on its own because it's not opinionated on what sort of app you're trying to build

I think either I wasn't clear, or you completely misunderstood me. My point, that Reason should have a standalone installer or package that gives you a working Reason as simply as possible without a whole build infrastructure required, is only bolstered by this statement.

I don't think it matters if it's the Reason-to-Ocaml targeted, or Reason-to-Javascript, or one for each, or one that includes both. Having to install one language, and then use tooling and package managing from that language to install another, strikes me as somewhat ridiculous in this day and age. just ship the entire tooling stack abstracted away.


I'm still not sure I understand. Are you complaining that Reason's distribution is optimized for JavaScript developers?


No, I'm complaining it's not optimized for the person that just wants to try it out in any way. Not everyone is using npm or already has Ocaml on their system. Making them install that entire toolchain first to try our Reason locally, is sort of crazy, it's just not the crazy that's easily seen when the costs are already completely amortized because you're a Javascript or Ocaml programmer already.

And locally is important, since they might want to try a simple app with it, and not want to set up a whole Javascript dev toolchain with webpack. Sure, they might end up going that way eventually, especially if they choose Reason and or React and integrate it into their project, but for a test drive, requiring it is a large hurdle and a lot more to keep track of.

Reason's current distribution method is akin to Python requiring the installation of a C compiler toolchain so you can download the source and compile. To be sure, that's a wanted distribution method of an open source project like that, but they've rightly recognized that as the only distribution method it would hamper adoption, especially on platforms where that toolchain is harder to get set up.

I'm not even suggesting Reason go as far as that, exactly. I'm suggesting Reason ship a tarball/zip with a directory structure that includes Node and a set of pre-installed packages that provide Reason/Bucklescript. Installation instructions would include setting a few environment variables (altering PATH, telling Node where to look for packages). Or instead of Node/npm, provide Ocaml/OPAM with the correct packages pre-installed (although that might be slightly harder due to an increased amount of binaries as opposed to interpreted scripts as with JS). Or both in the same package, if it's not an excessive amount of work.

I understand it's a lot of work, but at a certain point, expecting prospective users to install a whole toolchain not for your language, but for the hosting language, just so they can test it out your language ends up being limiting. You've said that Reason isn't trying to be opinionated in what kind of app you're trying to build, but I think it's still being very opinionated in the exact process required to build that app. It's just that you allow for two opinions instead of one.

Hopefully that's clear enough, and you understand this comes from an actual desire to make Reason better. I spent a couple weeks in my spare time earlier this year evaluating whether Reason would work well for a new project I was starting, and I was extremely excited by the possibility of a shared front-end/back-end codebase that could be compiled to binaries when needed for performance reasons. That ended up not working out because I think the ecosystem isn't quite there yet for that exact need (e.g. a good framework and ORM that's mostly in Reason, and doesn't require converting from Ocaml to reason, etc), but a big takeaway I got from that was that as someone not invested in the Node module ecosystem that much, setting that up, and in a way that was repeatable and documented, is painful, and that ended up counting against Reason in the end because I would undoubtedly have to deal with that. That's not to say I wouldn't with what I'm proposing, but if I'm already on the Reason cheer squad that's less of a problem, language adoption-wise.


Everything I've heard suggests ReasonML is targeted primarily at developers currently using NPM and working in that stack. I don't think creators of a tool have a moral obligation to make it easy to use for everything. Most things have an intended focus, and some happen to be really good for all kinds of other stuff too. That being said, it does sound like it would be cool for it to be easier to install without that dependency.

FWIW, Scala and Clojure require the JVM to work at all, and both are pretty popular.


The fact that BuckleScript/ReasonML doesn't look like it's intended to be used outside of the Node ecosystem really kills it for me. Js_of_ocaml has been a better experience.


I'm still convinced that in the world of frontend development, Ember is the only framework that hasn't screwed over its users.

My guess is that at Facebook there's too many smart people with differing opinions. Hence, we have to do an insane amount of research to construct the grab bag of pulling things together. And once that grab bag is complete, Facebook says "here's the new cool way to do it".

Ember on the other hand has happily given you the grab bag and has helped you support your production happens with the most professional, enterprise release structure.

Disclosure: Used to do only frontend development with Ember but switched jobs and now use React/Ember


You are comparing a view library (react) with a full framework (ember). Ofc you are supposed to pull things together with react, that's exactly what's intended.

Compared to react, ember is: slow (1), more difficult to learn (2), has a much smaller community (3) and, most important aspect to me, has a huge footprint (4). (I'm not against ember, it might have some nice aspects and features. It was really nice during the time when they released 1.0. But today I just think their are better options available)

1: https://auth0.com/blog/face-off-virtual-dom-vs-incremental-d... 2: https://guides.emberjs.com/release/ 3: https://github.com/facebook/react vs https://github.com/emberjs/ember.js 4: https://gist.github.com/Restuta/cda69e50a853aa64912d


I don't disagree with any of your points. React is faster. React has a larger community. All of it, I agree.

But. When it comes to productivity (actually building something and maintaining it), I can achieve way more in Ember.


I'm only guessing that's because you have prior experience with Ember and are only starting to use react now.

I find code written in ReasonML is 100x more maintainable than anything written in javascript, whether it's react or ember


Currently using Reason. Here's what they don't tell you:

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.)


> 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.

This was my experience as well. Also, while it may theoretically be possible to compile native code with reason, the core focus of reasonml is javascript frontend development at the moment.

> On the native side, since Reason's just a syntax transform: yes, they work with Reason too. But the native workflow is currently work-in-progress and needs polish.

https://reasonml.github.io/docs/en/faq.html


Yeah the native code story has been deferred and using OCaml directly is currently far easier. This will change.


Yea, thays been very much my experience as well. Still a little bit off usable imo, docs are still very iffy, and there's only really Real World OCaml as a great learning resource for the actual language.

refmt formatting drives me a bit nuts, especially the.lines thing; it's steadily improving though.

One thing though - Belt is the WIP standard library (so OCaml), whereas JS is just bindings to JS, they're very different things. Belt produces much better JS when transpiled, and it seems a lot saner than the stdlib, but it isn't really anything to do with JS bindings.

And the pipe operator is |>, afaics |. is a typo on the Promises documentation page?

|> for reverse application, @@ for application, so

    foo |> bar |> baz
and

    baz @@ bar @@ foo
are both the same as

    baz(bar(foo))
and they work excatly the same as in other ML languages


I don't know where (or if) |. is documented, I think I saw someone use it in a Github thread somewhere. I use it all the time – for instance

    someList
    |. Belt.List.map(i => i + 1)
... because most Belt.List functions take the list as the first argument, and |> feeds its input as the last argument.

Edit: apparently |. is BuckleScript, lots more discussion here: https://github.com/facebook/reason/issues/1452 ... just another instance of Reason still finding itself.


Ah, that makes sense. But that's, afaics, a completely undocumented operator which breaks standard (subject last) ML convention - I get why it's very useful for interoperability with JS but jeez that isn't great work on the documentation front; I've been using Reason for small personal projects and libraries for the last six months and didn't even know that was a thing that had been defined


Thanks for this. I was looking for a thorough comparison with Elm. If you had to start a brand new project, which would you choose? Do you believe that struggling through the <JS, Reason, Bucklescript, and OCaml> learning curve is worth it?


I don't know. Take a weekend and try out both, you'll learn what you like best. Both are great and frustrating at the same time, it depends on what you consider the bigger pain point. If you don't mind slow compile times, difficult JS interop, no JSX at all, lots of boilerplate, you can have code that is pure shining beauty and elegance (Elm) ... or you can have an absolute beast of an engine (Ocaml) covered in nasty duct tape with sticky residue and silver spraypaint on top (BS/ReasonML).

Give it two years though, and both will be amazing.


> shouldComponentUpdate is hard-coded to `true`

As in you can't override it? `shouldComponentUpdate` resolving to true in the absence of a custom method or PureComponent usage is standard React behavior: https://github.com/facebook/react/blob/7350358374036c0834ea6...


Well, you can (it's called `shouldUpdate` in ReasonML) but it doesn't work. You have to make it a reducerComponent, manually keep track of the previous props as if they were mutable state, and then do the comparison explicitly. This is from a conversation I had just a few days ago on the offical Discord chat.


There very well could be something I'm not understanding. What you are describing still sounds like standard React.JS behavior. Unless you use a PureComponent, or explicitly implement your own `shouldComponentUpdate` method, then `shouldComponentUpdate` will always resolve `true`.


You're not wrong; it's stateless components I'm talking about.

I should have been clearer: it'd be okay if `true` were simply the default, but the crux of the issue is that you can't even implement your own `shouldUpdate` as the function doesn't provide the previous props (like it does in React), so you have nothing to compare against – unless you laboriously store them yourself as state.


I'm going to blame any communication breakdown on the fact that I know nothing about ReasonML or React-Reason. However, the point of having to store state so you have something to compare against strikes me as a really odd choice for the React-Reason library to introduce, since it deviates from the functionality of React itself.

I was curious enough to glance at the React-Reason doc's and they say that `shouldUpdate` is passed a record called `oldAndNewSelf: {oldSelf: self, newSelf: self}`. Does that not have what is needed to implement the method without extra storage? For example, in standard React `shouldComponentUpdate` is passed `nextProps` & `nextState`, and since the method is in context of the previous render, we have everything we need to make the comparison without explicitly taking extra steps to store previous/next.

Maybe we are saying the same thing in different ways, I seem to be pretty good at that :).


No, you're absolutely correct. Coming from two years of React-ing myself, I went down the exact same thought path as you.

The documentation is outdated, and the {oldSelf, newSelf} doesn't exist anymore. You had to use the `withRetainedProps` component for this to work, but that now results in an error message on compilation, telling you to use a reducerComponent instead.

I think it's something they intend to figure out a better solution for, but it's been put on the back-burner and meanwhile we're stuck with a non-solution. (Unless this is all wrong and I've been lied to and there's a better way, in which case, please enlighten me!)


Ah, +1 for your point about the poor documentation.

Thanks for taking the time to clarify, and thanks for the original pros/cons post. I'm currently working on a mid-sized MVP project that is standard ES6 + Flow. I've recently been exploring our options for migrating to TypeScript or something like ReasonML. I've worked extensively with TypeScript, but am only starting to dip my toes into other options. You've been more helpful than just reading the documentation :)


You forgot the best bit... variants and pattern matching!


True! I suppose I'm comparing to Elm mainly.


Also for your issue with deeply nested options, have a look at this

https://medium.com/w3reality/working-with-option-using-maybe...


And if you don't want to implement the option monad yourself, there's the bs-abstract library, which contains a bunch of category theory definitions and implementations. I have gotten a lot of mileage out of it even in the small amount of ReasonML I have written. That plus ppx_let offers a pretty good monadic programming experience.


Those are both helpful suggestions, thanks guys. I've looked at some of those blog posts and github threads before but haven't tried it out.

In the end, however, it's more bolted-on pieces that should be part of the language if you ask me.


As a bit of a meta point, I find it really distracting when authors make random sentences bold. What you believe to be important is not necessarily what I'll find important, and the added emphasis breaks my flow.


Placing emphasis on things is commonplace. Sometimes it's in the form of a literary device such as hyperbole and sometimes it's done typographically. You shouldn't read it as being "random" but accept it as part of the works. The author clearly intended to draw attention to those sentences and given it is his or her article, it should be accepted as part of the article and the overall message attempting to be conveyed.


I'm fine with it when there's one or two. Every paragraph does not need an emphasized sentence.


I'm assuming it's more to help with skim reading.


This is best done using the first sentence of a paragraph. Make a statement first and support it with the rest of the paragraph. At least that's a style judges use on verdicts. That way I can skim a long text easily enough.

The opposite is having a conclusion at the end. That's used for opinions. A severe disagreement (not to say error) can be found faster if building an argument from the ground up.

If your conclusion is somewhere in the middle and scattered all over the place, you might want to highlight that indeed. I prefer stream of conscioussness for quick notes, but bringing it into a proper format can help to refine the argument.


I got curious about ReasonML when I recently applied to a frontend job that strongly preferred candidates with ReasonML along with the standard React and Typescript requirement.

I am using the approaching the mercenary approach to my career so I am interested if ReasonML would be a good long term bet. What do you guys think?


When I wanted to try Reason, tooling was just not there, coming from Elm, I was really put off by things being not more streamlined. I would keep an eye, as I like Ocaml etc, but at the moment Elm provides much better experience to me.

Oh yes, big thing is that interop with Reason is way simpler then in Elm.


The tooling has really come along since 6 months ago, FWIW. You can now get started by installing a single npm package[0], and editor support is quite good[1].

[0] https://reasonml.github.io/docs/en/quickstart-javascript.htm... [1] https://reasonml.github.io/docs/en/global-installation.html


Let me try it again, I kind of decided to wait it out a little bit until things are better :)

Thanks.


> A while ago I've written a series of articles about the Elm language and they are not that different from each other.

The main difference IMO is that Elm is not really a general purpose language, you must use the Elm architecture to use it. It is only meant for frontend web applications.


http://package.elm-lang.org/packages/chrilves/elm-io/1.2.1hi... elm is a frontend language, you are not forced to use tea. You can bypass the `program` entry point and use monadic-style command chaining for instance.


Sorry on the late reply, but your URL fails and I'm not sure I follow what you're talking about. I enjoyed Elm quite a bit @ version 0.16, then they got rid of signals and forced everyone to use TEA. To say that they aren't forcing you to use it isn't true. AFAIK, you can't even publish a module that interfaces with javascript without Evan's permission.


I'm always confused by statements like "You don't need Redux, you have reducer components".

Reducer components don't solve the problem of a centralized/shared/common state and interactions between components.


I thought this and was put off at first, but have come to the conclusion that you really don't need redux (I've used it thoroughly for years).

We've been converting a large JS react app to Reason, and strongly typed props solves a lot of problems. Passing props down multiple children is no longer a burden, and you'll never have that "prop spreading madness". For anything that reaaally requires some sort of global state, you can use the new react context api.

The only danger of writing in reasonml is spoiling javascript for yourself


>We've been converting a large JS react app to Reason

Is the process like say converting to using Flow where you can just add it in where you want and the application still runs fine, or by convert do you mean write a whole new application and when it's complete then launch?


Similar to flow. JS interop is great, so you can literally change bit by bit and refactor from the inside out.


> The only danger of writing in reasonml is spoiling javascript for yourself

Curing yourself :)


I think this is a valid point. I can't imagine effectively managing side effects without global state like in Redux.


Exactly my thought. It seems to me that it's just internal component state.. not application state


I think that Redux provides two things that people like:

1. A pattern to organize their state in that was testable and repeatable

2. A way to maintain global app state without prop drilling

I think that (1) is actually the reason that many people pick Redux in the first place. The amount of global, app-wide state in /most/ applications is fairly small IME. I think that the ReasonML team (which works semi-closely with the React team) is banking on things like Apollo, "suspense", the new context API and other things to further reduce the need for a global state store like Redux.

The ReasonReact devs are trying to follow the principal of least power in providing something that solves (1) for component-level state, which solves the 80%, and wait for the rest of the ecosystem to shake out for the rest.


I'm still waiting for the async stuff they have planned.


I've been a very heavy user of React with Flowtype. At some point, one would encounter the limitations of having just a type checker instead of a full-blown statically typed language. Also, the build story of the react ecosystem is not that great, especially with Webpack being so slow. There certainly are more issues that come with JS being JS. ReasonML looks like a good attempt to solve these problems. Certainly work checking out.


ReasonML is a big con.

It is clothed in ALGOL's syntax, but underneath it is a LISP with functions that can be stored, curried, passed around, and composed on top of one another. It doesn't have a Lisp-y syntax and thus no homoiconicity nor macros, but it does have PPX. (https://whitequark.org/blog/2014/04/16/a-guide-to-extension-...)

The biggest one that Reason pulls however is its syntax. ML based languages (Hope, Haskell, Miranda, F#, Elm, Purescript etc.) have historically used the ISWIM syntax (refer Peter Landin: The next 700 programming languages), which was designed to be similar to mathematical notation. Reason ignores this great tradition and brings ML to the bread-and-butter programmer with a syntax that is more ES6 than ES6 itself.

Reason is also the first language where the four major thoughts of PL design comes together.

It packs ML's type system, which lets you create user defined types on data, unlike Simula/C++/Java/C# which commingle user defined types and classes. Interestingly enough, Stroustrup had worked with Pascal the grand-old language of commercial programming, before he went on a great rage and wrote CFront/C++. Pascal was statically typed similar to how Reason/OCaml is. It allows you to define new types that work simply on the shape of the data without the ceremony of classes. But Pascal's type system at the time was quite limited - Stroustrup referred to it as strait-jacketed in HOPL II (Prof. Wirth had meant it only to be a language for teaching after all). Simula's types and classes however appealed to him, and that paved way for the class-based type system in statically typed object-oriented languages ever since.

But this doesn't mean that Reason doesn't have support for object-oriented programming. Reason is OCaml, and the O stands for "Objective", a nod to its object system that knowledgable people like avsm has averred to as fantastical.

The Lispy roots of Reason/OCaml makes it functional, which in simple term means value-based programming, primitives like fold and map defined with recursion, and linked-lists are used for almost everything, except when it isn't. Xavier Leroy, who is both the author of Coq and OCaml is a pragmatist - the OCaml compiler code is choke full of mutation and OCaml has strong support for imperative programming but tastefully cordoned with an explicit syntax.

It is a langauge that mixes imperative, procedural, object-oriented, and functional paradigms, sitting just at the confluence of the great PL traditions that includes ALGOL, Simula, LISP, Modula, ML, and ES6 (!). It is functional programming for the masses, finally delivered!


Does ReasonML have ML's nice module/functor system? That would be a huge advantage over elm.


Yes it does. I had to build an autocomplete functor which generates an Autocomplete component for arbitrary types when I used ReasonML for my personal budgeting app.


do you happen to have code online?


I just pushed to github.

Here's the functor: https://github.com/tonyhb/reasonable-native-budget/blob/mast...

Here's the functor being applied: https://github.com/tonyhb/reasonable-native-budget/blob/1f69...

Caveats: haven't committed some time and it was my first ReasonML/React Native app.


Throwaway since embarrassed to ask this: What is the knock against Javascript?

Not trolling, besides lack of types it seems like a pretty darn solid, ubiquious, elegant/straightforward language to get things done.

For people with strong opinions about this, what is so horrifying about Javascript to you?


Since moving from javascript to reason/ocaml, i'm genuinely nervous about refactoring Js now. Helpful compiler errors are literally life changing, and being able to handle options with Some/None means no more nasty undefined bugs.

You can do a lot of funky things with javascript, and it's easy to convince yourself that because you can do it, you should do it. With reason I've found I can achieve pretty much anything with a far more concise set of tools, and I can't hack my way around problems - I'm forced to deal with them the correct way.

Being forced to do things in a certain way has a massive benefit, and encourages consistency. You can look at 5 different javascript projects and each one of them will most likely be completely different.


It's not just the lack of static typing. It's weakly typed, so implicit conversions can happen when you don't expect them. A standard library which lacks the most basic functionality. Historical baggage(arguments, var, ...). Prototypical inheritance without proper language support. null vs. undefined. Async by default (that point may be debatable ;)).


JS got a bad reputation from the pre-ES6 years. Before ES6 it really was a dumpster fire. It'll probably be many years before all that bad reputation can be redeemed as people slowly discover how good ES6 is.


I love JavaScript, but also recognize when some other things are better (in the useful, pragmatic, non-edgy, non-trendy sense). Bucklescript/reasonML seem to be a way to use something better and keep what I like about JS without starting at zero in the job market or ecosystem. Specific example: if reasonML gets big enough then all react jobs are potentially reasonML jobs. In the bigger picture, purescript/elm/bucklescript/reasonML/clojurescript all have one problem. There's a lot of hype about how much better they are, but also the job market for them is nearly empty. This makes it difficult to justify spending a lot of time evaluating them before the jobs exist. I end up using flow or typescript in the short run.


Javascript has mutable datatypes and weak typing by default - that makes it easier to write buggy code than making it harder to do so.

To write nice JS, you have to be disciplined and very cognizant of what you're doing. And then you have to deal with the rest of the ecosystem, which is massive and of varying quality.

I recently ran into mutable date types in momentJS, which is a frustrating gotcha - it's not flip the table lose your shit annoying, but it's simply a non-existent issue in other languages.


I tend to disagree with: darn solid and elegant.

It is easy to write flaky code in JS and rarely the language helps you to go for the elegant solution. On this front ReasonML brings huge value to the table.


Somewhat OT, but is the origin story of React written down completely somewhere? I often see bits and pieces like how it was originally prototyped in ML, would like to know more.


Using Facebook's software supports Facebook. I think the industry should move away from that instead of adopting more of their technology. Programmers should start considering these things.

Alternatives: Elm, Purescript, etc.

Edit: I recommend stopping and thinking a bit about ethics of technology choices before reactively downvoting.


Of all Facebook tech, this is the least "Facebook" of them all. ReasonML is a thin layer on top of OCaml, a language that's been around for decades. If Facebook one day abandons Reason, it would their loss more than anyone else's.


That doesn't really address the issue that the use of Facebook's software supports Facebook. The industry needs to pay more attention to the long-term results of its choices and actions.


I'm not sure what the connection is here. Is it because Facebook sponsored development of Reason? Should we consider not using anything that Facebook touches?

What if Facebook pays a developer to work on another popular library like Vue.js? Should we consider stop using Vue?


As far as I know, they aren't a sponsor of the project -- they own the project (as opposed to something like Cassandra).

Companies release these libraries because they benefit the companies. The successes of projects like React help Facebook.

I think that people who believe that Facebook is an unethical company should consider alternative technologies on new projects whenever possible.


> Companies release these libraries because they benefit the companies. The successes of projects like React help Facebook.

The success of projects like Haskell and OCaml help Facebook too. Should we consider not using those technologies?

It seems the only difference you can point out is that Facebook "owns" React. But this doesn't make any practical difference when it comes to open source. It's like public transportation. If Facebook sponsors a high-speed railway that benefits both them and two cities, so what? That's great for everyone.

If you were talking about a paid SaaS run by Facebook, then I would agree with you. That would be more analogous to supporting Uber than supporting public transportation.


Facebook's use of software is completely different than a product of Facebook that targets programmers. Companies release open-source libraries because they benefit the companies.


Maybe we can think of this as Facebook's payment to us for using our data.


Completely agree. We all have to capitulate sometimes, but rarely with new, less-used tech. I have the same feeling towards GraalVM. Sure we may use Java, React, etc because their ecosystem outweighs their maintainers but that doesn't mean we have to with lesser-adopted things. Reduced adoption is also the best, least-judging way we can send messages to high quality developers that remain at these places.


There are alternatives to React too, like Vue.


Hm I've been saying that for a while but no one seems to understand the connection, or care.


It takes time. Everyone who considers these issues should speak up.


Interesting... we covered ELM a few weeks ago: https://www.imaginarycloud.com/blog/elm-javascript-reinvente...


One reason I don't use Elm and Purescript is that enforcing the purity of functions can be a pain. While pure functions are great in theory, sometimes having a non-pure function is much easier, and I'm okay with my codebase being 99% pure functions.


PureScript has a lenient FFI so you can choose to use 99% pure functions if you like (at your own risk).


My point is more about ethics in tech than a specific language. I expected downvotes, but wish that the industry were different.


We can always fork these things if it comes down to it.


If it were going to be forked, then it would already have been forked. The unethical nature of Facebook is not well-hidden.


But can it app?





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: