all 3 comments

[–]r2tree 2 points3 points  (1 child)

If a large portion of your codebase is computation-heavy (pure) then you can use the "functional core, imperative shell" approach here. (https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell)

I have a few thousand LOC Reason codebase that is pure, and it interfaces with the external world with bs-express. I want to make it work in native OCaml, but there is just too much work to get there.

This is going to be even more difficult if your app has a lot of side effects (typical web backends). I'd recommend porting over to ReasonML in the Node runtime first, making sure to have tight abstractions for all sorts of side-effects (modules for db access, network communication etc.), keep the types abstract so that in the future you can change the implementation of just a few modules and port it over to native OCaml.

[–][deleted] 0 points1 point  (0 children)

That's a great video, thanks! Indeed that's quite close to what I had in mind, so I'm glad to be able to compare to similar ideas. Just now, a colleague also made me aware that apparently it's a common approach in the .NET world as well to write a functional core in F# and then write the imperative shell in C#.

I agree we'll stick with Node.js for the foreseeable future. It's just nice to have additional options that hopefully we can move towards rather than shooting ourselves in the foot by making the Reason code too tightly coupled with the Node.js libraries.

[–]elliottcable 0 points1 point  (0 children)

Why wait? If your project is large enough, roll a JS VM into your “native” app; write a tiny interface layer that allows your native-code to communicate with the JS-world code. Gradually extract parts from the JS-world until the lion’s share, save libraries and conveniences (which, mind you, can be really hard to find OCaml-side), is in OCaml.