A couple million lines of Haskell: Production engineering at Mercury
101–110 of 249 posts
Re: A couple million lines of Haskell: Production engineering at Mercury
#102> Haskell gives you tools to encode these incantations in types so they cannot be forgotten. This is, for my money, the single most valuable thing the language offers a production engineering organization. Haskell is admittedly, probably the most powerful widely (or even somewhat widely) used language for doing this, but this general pattern works really well in Rust and TypeScript too and is one of my very favorite…
my experience is that ocaml is more powerful than rust for enforcing this sort of type safety, because you have gadts that give you more expressive power, and polymorphic variants and object types (record row types) that give you more convenience. and the module system and functors of course.
you also avoid some abstraction limitations/difficulties that come from the rust borrow checker for places where garbage collection is just fine
Re: A couple million lines of Haskell: Production engineering at Mercury
#103Re: A couple million lines of Haskell: Production engineering at Mercury
#104> Haskell gives you tools to encode these incantations in types so they cannot be forgotten. This is, for my money, the single most valuable thing the language offers a production engineering organization. Haskell is admittedly, probably the most powerful widely (or even somewhat widely) used language for doing this, but this general pattern works really well in Rust and TypeScript too and is one of my very favorite…
I'm not convinced it really works well in typescript. the lack of nominal types requires you to remember some pretty hacky incantations if you want something like a newtype wrapping a primitive type my experience is that ocaml is more powerful than rust for enforcing this sort of type safety, because you have gadts that give you more expressive power, and polymorphic variants and object types (record row types) that…
Somehow, it feels like a better solution than these complicated type systems. Does any other language do this outside BEAM?
Re: A couple million lines of Haskell: Production engineering at Mercury
#105Earlier quoted context omitted.
As somebody who has helped hire many Haskell devs, I can say that lots of Haskell experience isn't always a positive. We have to filter carefully to make sure that we end up with developers who want to build real things, not developers who just want to get paid for noodling around with Haskell. As far as I'm concerned, I'd much rather hire somebody with lots of experience building things who ended up coming to Haskel…
haha i've abused this recruiting mindset for a decade it's so easy to scout when a company has this haskell philosophy. either by the interviewers themselves or by the bloggers they hired to guide their team. the trick? i just..lie. "oh yeah i'm super pragmatic. i'm not hardline about haskell. i don't think you should be fancy." see how easy it is? i am suddenly hired and got a fat raise. and if the company moves off…
Congrats I guess? Not sure where the abuse/guilt comes from.
Re: A couple million lines of Haskell: Production engineering at Mercury
#106Earlier quoted context omitted.
This isn't specific to Rust or Typescript. You can do this in basically any language. Imagine you have to distinguish between unescaped and escaped strings for security purposes. Even with a dynamically typed language, you can keep escaped strings as an Escaped class, with escape(str)->Escaped and dangerouslyAssumeEscaped(str)->Escaped functions (or static methods). There's a performance cost to this, so that's a tra…
What you cannot do is compile-time safety guarantees, and in languages like Rust type system isn't strong enough to do some advanced compile-time guarantees (via types). So no, you cannot do this in basically any language (unless you turn it into Haskell).
Re: A couple million lines of Haskell: Production engineering at Mercury
#107Earlier quoted context omitted.
I'm not convinced it really works well in typescript. the lack of nominal types requires you to remember some pretty hacky incantations if you want something like a newtype wrapping a primitive type my experience is that ocaml is more powerful than rust for enforcing this sort of type safety, because you have gadts that give you more expressive power, and polymorphic variants and object types (record row types) that…
It really feels like we’re solving the wrong problem sometimes. If a bad type can crash your application, sure, type safety is one answer but I have to admit I like the erlang approach; if something unexpected happens crash the process (not os process, erlang process) which has a very small blast radius on a well architected system (maybe doesn’t even fail the individual request that caused it). I wish more languages…
But I did want to add something the article also touches on: types can be not only about ensuring safety or correctness at runtime, but also about representing knowledge by encoding the theory of how the code is supposed to work as far as is practical, in a way that is durable as contributors come and go from a codebase.
Admittedly this can come at the cost of making it slower to experiment on or evolve the code, so you have to think about how strongly you want to enforce something to avoid the rigidity being more painful than valuable. But it's generally a win for helping someone new to a codebase understand it before they change it.
Edit: another thought I had is that type mistakes do not always causes crashes. Silent corruption can be much more insidious, e.g. from confusing types which mean something different but are the same at the primitive level (e.g. a string, number or uuid)
Re: A couple million lines of Haskell: Production engineering at Mercury
#108Earlier quoted context omitted.
They are different things.
What are different things?
Haskell type classes are not classes (like Java or PHP classes); they are comparable to Rust traits -- which are different from PHP traits which are comparable to Java/C# interfaces (with default impls; if you just want contracts you have... PHP interfaces).
A fundamental difference is that you can instantiate/implement a type class (or Rust trait) for any* type, compared to interfaces where each class declares the interfaces it implements. You can therefore create generic (forall) instances, higher kinded type classes, etc.
Re: A couple million lines of Haskell: Production engineering at Mercury
#109Re: A couple million lines of Haskell: Production engineering at Mercury
#110Earlier quoted context omitted.
I appreciate Rust for making affine types mainstream, and having at least the C++ community start caring about security, even if half hearted. However I share your conclusion, outside scenarios where having automated resource management as the main approach is either technically impossible, or a waste of time trying to change pervasive culture, I don't see much need for Rust. In fact those that write comments about w…
I think Rust would be fine for application code if it kept the borrow checker, but had greater allowance for dynamically-sized variables, or even garbage collection. The reason calling things through an interface is so tough in Rust is because doing so requires having a pointer to a value of unknown size, which involves either heap allocation or alloca(), neither of which are very happy in Rust. Many of the other thi…
This is also not strange for those in the Rust community with type systems experience, hence the Roadmap 2026 proposals for a more ergonomic experience.
Thus we have Linear Haskell, Swift 6 ownership, D ownership, Koka, Hylo, Chapel, OxCaml, Scala Capabilities, Ada/SPARK proofs, Idris, F*, Dafny,....