Decided to join this conversation and share my very recent experience.

We recently switched from Haskell to Scala for a new project due to the scope of the JVM ecosystem, in spite of having inline-java available in Haskell and GHC‘s excellent FFI.

We’re a team of mathematicians and physicists working in finance (not a fintech company though). Originally we chose Haskell because it felt as the most natural fit to us to expressing our domain models and producing great EDSLs. But now it looks like we‘re going to transfer all prospective projects to Scala.

It took some time to get used to it. At first the syntax felt unergonomic with Scala 2.13. Scala 3 / Dotty seems to have improved over it significantly. And the functional programming libraries come to the rescue.

Scala’s standard build system, the sbt, is a boon, we got to really like it.

Then the differences in the semantics occupied me for a while, but I managed to quickly get used to them. Except perhaps for the local type inference. However, with certain GHC extensions, the program becomes undecidable anyway, and we have to specify the types here and there despite the global HM style inference. Overall it still feels like I can more easily express type-level programs in Haskell rather than in Scala. GHC Haskell feels just more expressive and powerful. But this is likely to mostly be due to me having written Haskell for several years now.

However, me and my folks all have become significantly more productive in Scala 2.13, and even more so with Scala 3, than we were used to with Haskell. You can do the easy things the easy way.

it’s awesome that in Scala you get the benefits of both worlds, and can commit to explicitly managing effects when you’re ready, laying ground for quick prototyping and cost-efficient MVPs. You simply get the opportunity to run more experiments in your business area rather than in the programming language theory.

With ScalaCheck there’s a QuickCheck for Scala, there’s also a couple more for the JVM. ScalaTest is more than good enough. MUnit is also nice. Due to the different type system, we had to extend our testing. There are also great integration and end-to-end testing frameworks for Scala and the JVM. So we’ve mostly covered our implementation risks. I’m unaware of anything for which GHC would provide stronger guarantees for our services.

We run and maintain several services written and executed on another managed and unmanaged platforms. We benchmarked some of their aspects with almost identical implementations in Scala, trying to translate certain idioms to a more natural Scala style. Well, we were surprised to see how extraordinarily well our Scala services performed, we even outpaced a highly optimized Go service, but we couldn’t match a modern and optimized C++ service whose implementations only few folks in my team understand, more or less.

In other words, we’re extremely satisfied with Scala 2.13 and 3.0 through 3.1. Binary compatibility is attained through cross-compilation with a couple caveats pertaining to certain old-style macros. So we’re mostly certain that we’re sticking now with Scala.

For front-end development, there‘s also GHCJS which transpiles Haskell to JS and PureScript along with Elm transpilers that are great for the front end, with Elm being extremely performant but sometimes quite painful. We went with some PureScript + React and were mostly satisfied. We haven’t dealt with front ends in Scala.js yet though.