Hacker News new | ask | show | jobs
by bjz_ 2196 days ago
> OCaml's is also excellent but not immediately obvious (their docs have improved a lot)

Interesting! The last time I tried OPAM, it actually seemed more frustrating than Cabal! Maybe it's improved? Last time I tried OPAM it would install packages globally by default, and avoiding that was a confusing process, when that should be the default behavior.

Cargo (while not perfect) has really nice defaults out of the box - ie. it generates a lockfile by default, scopes packages locally to individual projects, and lets you use more than one package of the same version in the same project.

Really hoping OCaml and Haskell can improve their package management story - they are getting there, but it still holds me back from really using them on a daily basis.

6 comments

A bit off topic, but is Haskell viable for production? Or is it just really intended as an experiment? Is it worthwhile to jump into Haskell now, or perhaps one should look into Idris or Agda? Any companies using Haskell where it has proven a distinct advantage?

Ocaml and SML (the former being sadly quite unpopular these days) are an order of magnitude simpler than Haskell. They are easy to master. I have been quite productive with Scala which, while being a member of the ML family, is much more intricate due to OO + FP on top of great Java interop and many Haskell-like features (laziness, monads, lenses...).

Haskell doesn't feel the same. I have learned some Haskell over the years. Since I come from a pure FP education (started with SML) and I have lots of type theory background, everything feels familiar, yet I've found it really hard to be productive or to justify the mental overhead of laziness. I have developed some small projects in Haskell, but I haven't found it a productive alternative to the languages above.

My company writes and supports a lot of custom Haskell software for our parent, an ISP up in Alaska.

What we gain is a high level of confidence in our business logic rules due to strict typing, fewer overall tests, and by avoiding a few small gotchas uncrashable runtimes.

Not to say it doesn’t come without problems. Poor IDE integration (I personally don’t care), questionable documentation at times, and a steep rewrite your brain learning curve.

Some posts I have written.

https://www.alasconnect.com/2018/10/02/introducing-haskell-c...

https://www.alasconnect.com/2018/10/04/productive-haskell-en...

http://blog.bojo.wtf/2020/04/15/is-haskell-a-bad-choice/

I'm the CTO at Mercury (https://mercury.com/) and we have 100% of our backend written in Haskell. It's gone really well so far.

Answering another commenter's question, I would say the "secret weapons" are:

1. Hiring: Haskell is a very in-demand language by very good engineers. For a startup, it's absolutely amazing for recruiting and I can't overstate how important recruiting good people is for a startup.

2. Correctness: Haskell helps you ensure your code doesn't have bugs. For a bank this is fairly important. Some aspects of Haskell that are great for this: algebraic data types ("discriminated unions" in some languages) model business logic quite well, purity makes a function much more of a known quantity, libraries like Persistent ensure type-safe SQL queries, and in general the community cares about correctness.

I haven't used the other languages you mentioned, so I can't really speak to a comparison with them. Re: laziness, it's almost never something I think about in practice.

> 1. Hiring: Haskell is a very in-demand language by very good engineers. For a startup, it's absolutely amazing for recruiting and I can't overstate how important recruiting good people is for a startup.

Although for engineers, supply-and-demand favoring employers typically means it disfavors employees: you may effectively be taking a pay cut to use Haskell compared to more popular languages.

Sure, but those that are willing to because they're sufficiently excited about the language means you can have a higher confidence in your hires, since they, A. Know what Haskell is, B. Want to learn it, C. Are willing to take a pay cut to be able to get paid to learn/use it. Very high signal to noise I'd wager.

If you're a Java shop, you better be paying higher than market rate if you want to be able to attract good talent, but then you still have to figure out who they are amidst all the mediocre/poor devs, who are interested because of the higher comp. Very low signal to noise.

It seems like a less popular language, that has real business value, helps achieve the thing every company that isn't "hire fast, fire fast" tries to do with their hiring policy. It does mean you can't easily hire people who already know the language, so you have to consider the ramp up time, but I don't think that's nearly as painful as many hiring managers seem to think it is.

Well yeah, it seems you're reiterating that it's great for employers, not for employees. I don't disagree.

Of course if Haskell somehow takes off and all the FANG companies want to hire as many Haskell engineers as they can, then the situation would probably reverse.

I'm more calling out that it's mutually beneficial; the employees choosing that tradeoff are still choosing that tradeoff. The other tradeoff, work for a higher compensated position in a language that they hate, isn't objectively "better", just different.
The labor market is not zero-sum.

If Haskell is just a signal that selects for more competent people, companies will be happy to hire people whose competence they would have to invest a lot to match otherwise, and developers will be happy to get a larger salary than they would be able to get otherwise. (But yes, this would disfavor people with other kinds of signal.)

If it selects for high productivity people, or if it helps people be more productive, companies will be happy from getting more output than they would otherwise, and developers will still get more money.

The stereotype is that Haskell jobs pay less, and developers are happy to work with a better language. That still doesn't disfavor any party, but I don't think anybody has any evidence that this is the case. Notice that the GP is talking about people competence, not salary.

You really think so? Take for example, kdb+/q. Not exactly widely used, but engineers who specialize it are making top dollar, it's not unusual for total comp to be around a million dollars, or sometimes a lot more, if you're the principle architect of a new system.
You're just saying that kdb has the opposite imbalance as Haskell (relative to mainstream languages).

If supply and demand for kdb favours employees, then presumably it disfavors employers, who would rather have a bigger pool of kdb programmers so they could pay less.

That doesn't contradict what I said about Haskell vs mainstream languages. I didn't say all niche languages are like Haskell.

To answer your questions literally without much nuance:

Yes, Haskell is viable for production. There are caveats, as with any other language. Haskell has more caveats that most other languages you would be familiar, but it's nonetheless perfectly suitable in the right environment.

No, don't use Agda or Idris in production, they're totally unfit. Agda is not intended to be. Idris may be but it will take 5 or 10 years.

The only members of the ML family that I'm aware of are Ocaml and the flavours of Standard ML. Only Ocaml is fit for production.

> The only members of the ML family that I'm aware of are Ocaml and the flavours of Standard ML. Only Ocaml is fit for production.

F# is also a member of the ML family and is totally fit for production.

F# is the language I want to like, and would like to use in prod, but it constantly feels like the ignored step-child.

The REPL is great in theory, but trying to import packages is a nightmare every time I try.

Dependencies exist, but they all seem to target wide and inconsistent range of the ecosystem. Want to target dotnetcore 3.1? Good luck have fun: everything you find useful is targeting some combination of standard/framework/core/whatever confusing variant Microsoft decides to come up with this week.

If I somehow convinced my co-workers to adopt a language that wasn't C#, I'd point them Rust or Haskell instead.

Most of those package issues also apply to C# particularly as it stabilizes towards .NET 5. However it isn't too bad once you get it; and for most standard use cases it seems to work with the dotnet cli out of the box. Many people seem to be productive with C# so I'm not sure how big of an issue it is other than the small initial learning curve but many package managers have that (IMO Maven is harder yet many people use that in Java space and not too hard once you learn it).

REPL's often have problems with package management in a number of languages as they often have a different build chain from the compiled style apps which have the chance to resolve packages. When doing .NET Core in the past I know Paket can generate these scripts for the REPL to import packages (seen csx/fsx scripts for each package) - but another comment alludes to a more supported way in the future which is good.

Doesn't seem like you have a problem with the language per se; rather the package management story for .NET Core.

I totally agree with your points but the situation seems to be improving. With https://devblogs.microsoft.com/dotnet/announcing-f-5-preview... you can import nuget packages in fsx scripts. The dependency situation also seems to grow saner every month.

Nevertheless i would still wait another few month for things to stabilize with .net 5.

I think that F# is ok for production. I used it at a previous job without too many pain-points, especially in comparison to Haskell. I'm not a huge fan of MSBuild, but it works relatively well, and of course you have access to the massive .NET library and the entire ecosystem of C# libraries out there, and there's even some tooling to make the C# stuff play nicely with the F# constructs.
I totally forgot F# was part of the ML family, but can't edit my comment now! Thanks to everyone who replied to correct me.
There's ReasonML, which compiles to JS and seems intended for production
Reason is a syntax layer on top of OCaml, so it shares OCaml's production-readiness. The tooling that Reason uses to compile to JS (Bucklescript) was originally designed for OCaml, and Reason supports native targeting via the plain OCaml compiler backend as well. It's a pretty pleasant ecosystem at the moment.
In the same space we also find Fable, which hooks into Babel to compile F# to JS. We're using it in production and it's been surprisingly good. It's very nice to be able to share the definitions of data structures between the C# backend and JS (via F#) front-end.
ReasonML serves no purpose whatsoever. The syntax is worse than OCaml's (though, more regular) and the editor tooling is really awful. OCaml compiles to JS just fine.
Idris 2 is a big step towards a production grade FP language
> A bit off topic, but is Haskell viable for production? Or is it just really intended as an experiment?

It's viable for production and there are businesses which use it, notably fintechs. Also Facebook for some things (Facebook employs Simon Marlow [1]). And I know this is an irrelevant anecdote, but I have a friend who has been working in several startups which use Haskell for the last few years. Like Paul Graham has argued of Lisp, Haskell really is a "secret weapon" and people who use it for production tend to love it.

EDIT: a prior version of this post claimed Facebook employed Philip Wadler, which is incorrect. Sorry! I got my wires crossed and confused Philip Wadler with Simon Marlow!

[1] https://www.linkedin.com/in/simonmarlow/

> Haskell really is a "secret weapon" and people who use it for production tend to love it

That's exactly my question. I'd be really interested in hearing about domains where Haskell is a secret weapon and how it compares to ML family languages and dependently-typed ones.

I did a bunch of professional Haskell work in a prior life[1]. Most of its 'secret weapon' status springs from the way Haskell lets you control side effects.

We had a fantastic unit testing harness[2]. With effect tracking, you can arrange for your harness to put precise fences around nondeterministic code. You don't need to rely on experience and discipline to ensure that tests are reliable or fast. The type system does it for you.

Effect tracking also makes concurrent code easier to write. You have a great deal of control over how and when threads can be created, and what kinds of logic is permitted on those threads.

GHC's IO manager offers green threads and async IO, so rather than a select loop, you just fork threads and perform "blocking" IO calls. You get about the same efficiency as a select loop this way.

Lastly, something we learned to appreciate over the years is that Haskell is easier to refactor. When you combine the rigid type system, effect tracking system, and ease of writing unit tests, it becomes very easy to refactor old Haskell. It doesn't really matter how bad the old code was or whether the original author is around to help you at all.

If you intend for your product to evolve continuously forever, this is truly a secret weapon.

    [1] https://andyfriesen.com/2014/03/25/what-its-like-to-use-haskell.html
    [2] https://andyfriesen.com/2015/06/17/testable-io-in-haskell.html
Of all the things I like in haskell (having only used it a as a hobbyist), refactoring tops the list. It's a lot less scary to refactor when the compiler tells you so much about which parts you missed.
I'll let people who actually use it -- instead of toy with it, like myself -- answer you. I know many haskellers read HN and have answered similar questions in the past.

Like I said, I do know Haskell is used at fintechs (source: a friend whose job is precisely that).

Facebook employs Wadler? Since when?
Gah! I meant to say Simon Marlow [1], co-developer of the Glasgow Haskell Compiler (GHC) [2]. Sorry for the confusion, I'll edit my other post now.

  [1] https://www.linkedin.com/in/simonmarlow
  [2] https://en.wikipedia.org/wiki/Simon_Marlow
I've got a REST API in production linking to postgres and rabbitmq and I'm very happy with the performance and maintainability. The ecosystem is a bit more bare than with other languages like node, python or java but in exchange the paradigm and type-system lets you build safe and well isolated code. In my opinion it's also quite easy to read despite being terse.

Despite the complaints the build tooling is good, and there are decent plugins for IDE capabilities although they're a little bit resource hungry.

My biggest problem is the lack of component libraries, for example I wanted to use SMTP a little while ago but couldn't find a library compatible with the latest GHC so ended up writing a python script connected to rabbitmq.

For business logic involving timezones, currencies, API calls, calculations etc. you're pretty well covered though.

I’ve used it on multiple projects for clients over the last 5 years. These projects were large, made it to production, and were successful. I love it. Once you clear the initial learning curve it feels very productive, and gives you the feeling of always having something more to learn and master.
What domains?
Hasura (one of my favourite technologies) is built with Haskell!
> Really hoping OCaml and Haskell can improve their package management story - they are getting there, but it still holds me back from really using them on a daily basis.

Cabal 3.x with Nix-style buildscovers all packaging needs that I ever had with Haskell ecosystem[1]. And there's a new wave of tooling based on incremental Nix builds, that you can begin using today [2]

[1] https://cabal.readthedocs.io/en/latest/nix-local-build-overv...

[2] https://github.com/nmattia/snack

Yeah, it's really great to see the progress there. However, afaik, it still doesn't freeze packages by default, or let you have multiple packages of the same version in a dependency tree[1]. The former can be worked around, but it's annoying that it's not the default. The latter is more frustrating however!

[1] https://news.ycombinator.com/item?id=23454711

Stack does this, if I understand what you're saying. Stack+nix has worked quite well for me for a few projects.
Yep. Cabal 3.x is great, better than anything else I've seen for any other language.

As the article says, it just needs to correct the default behavior (deprecating the old behavior is on the roadmap, interestingly, the documentation doesn't even say what is the standard right now) and some improvements on usability (just better docs goes a long way).

By default, opam installs everything into the current "switch". Typically you have switch one per compiler, but you can create one per project. You can also create a "local" switch directly inside your project directory: https://opam.ocaml.org/blog/opam-local-switches/

Another option is to use the duniverse tool (https://github.com/ocamllabs/duniverse). That downloads all dependencies to the project directory, and then builds them all together as one giant project. That makes it very easy to make changes across multiple libraries at once, while keeping fast incremental builds.

And a final option is to build projects with Docker, which allows you to have separate versions of non-OCaml packages too.

Ahh cool - had some similar questions here: https://news.ycombinator.com/item?id=23460980 - mainly, how much manual switching do you have to do? Or is it seamless, depending on what project directory your in? I think I tried the local switches in the past and got really confused when switching projects and everything broke, thinking 'wasn't all this meant to prevent this?'.
Packages are not installed globally in opam by default nowadays. `opam switch` "enables the user to have several installations on disk, each with their own prefix, set of installed packages, compiler version, etc". https://opam.ocaml.org/doc/Usage.html#opam-switch
Oh that's nice to hear! Some questions:

Do you have to run this command manually, and does it mutate the shell state? That's one thing that frustrated me with opam in the past as well. I couldn't just jump into a directory and build a thing, then switch to another project directory - there was a lot of manual switching and unswitching of packages if I recall correct?

Is it possible to install multiple tools globally using opam that use disjoint library versions? Like, I might want to install Abella and Coq side-by-side, but they might have conflicting version requirements. I think I was super excited about opam 2, then tried installing one thing, only to have it break again when I installed something else.

Is it possible to have multiple versions of the same libray in the same project, or does the constraint solver need to find a single solution for each library? [1]

[1] https://news.ycombinator.com/item?id=23454917

Sorry I miss your reply. I create opam switches to have different versions of compiler, or allow libraries that conflict to live at different branches.

1. Dune is a relative new build system for Ocaml. You just write a configuration file, and dune will handle switches automatically. "It also supports multi-context builds, such as building against several opam roots/switches simultaneously. This helps maintaining packages across several versions of OCaml and gives cross-compilation for free." See https://opam.ocaml.org/packages/dune/

2. Yes. You can can multiple versions library at different switch.

3. I am not sure.

I got told some months ago to look for these docs: https://news.ycombinator.com/item?id=22395595

It seems all we want can be made to work but it does require some tinkering and being aware of the tools' options.

Maybe you tried it before v2? Imho opam now is very usable, lets you be productive for 95% tasks after reading a 5min introduction, and generally gets out of your way.