Hacker News new | ask | show | jobs
by tathougies 2987 days ago
At my workplace, we use my database library [beam](https://github.com/tathougies/beam) to make sure that our queries (written in a Haskell-like DSL) are runnable on the backends we choose.

Also, I've found the cognitive burden to be significantly less using my beam library than writing SQL. The library handles everything. We freely join against queries (which may themselves be the results of joins, aggregates, window functions, etc). The SQL produced is what you'd expect. If you try to do something that is not straightforward on the backend, the library complains at compile time, and can even offer suggestions. We don't even need to worry about NULL, because the library makes heavy use of type families and such to guarantee you won't see a SQL NULL unless the type says so. If you use standard beam operators, we handle NULL sensibly. You can also drop to SQL NULL, if you want to have tighter control, but this causes the types to change, which means you can't do anything silly (like inadvertently throw out rows because your join condition now evaluates to NULL when you didn't want it to). Ultimately, using the type system is wonderful. Best of all, the types are mostly inferred. I rarely write out explicit type signatures. Despite the types carrying significant computation, all of that is given to us basically for free.

Once we have linear types in GHC, the migrations system will be able to check that a migration script is valid from beginning to end before the migration is even run! There's no way you could do that with any current tool I know of.

My guess for why big game engines aren't using higher-kinded types is that they are not available in any common systems level language. The only systems language I can think of with HKTs is ATS, which is a bit obtuse.

W.r.t cache efficiency, I've been working on a library to exploit the Haskell recursion-schemes package to transparently store and read data in a cache-intelligent way. It's certainly possible to do, it's just not necessary for most of the kinds of programs Haskellers write. At my last workplace we used Haskell for protocol parsing, and we were able to parse gigabits per second using just the standard Haskell containers and such. Haskell is quite a fast language, if you use it correctly. You rarely need heavy optimizations. Although obviously for game engines, you probably would.

1 comments

> Also, I've found the cognitive burden to be significantly less using my beam library than writing SQL.

I find this confusing. You still have all the cognitive burden to figure out what SQL you want to write, but then you have to translate that SQL into Haskell (or any other ORM).

Interestingly, this is not the way it works with beam. You have to figure out what query you want to write and then you have to translate that to beam. That correspondence is natural because beam is close to relational algebra. Then beam generates SQL automatically, again very naturally because beam is close to (the semantics of) SQL.
Ah ok, you're talking about SQL as being an abstraction from relational algebra. Yes I wish more people thought about SQL this way but I'm not sure how many actually do.

I can see that this would be a benefit in the long run, but it wouldn't be familiar to most devs in the beginning. Similar to learning Haskell, once you get over the hurdle of the concepts then there's less to think about over all but there is still that initial gap.

Certainly the declaritive nature of SQL should be a very good fit for Haskell.

Interestingly enough, Haskell has an inefficient version of the relational algebra builtin. The default monad instance for list provides all the semantics you need. Beam steels from this intuition. Most Haskell developers are familiar with using the list monad, so things come somewhat naturally.

The types go a bit crazier than lists internally, but the aim is minimize the times manual intervention is required

I really feel the is some what of a confirmation bias with these statements from Haskell users. They have spent so much effort into mapping problems to cat type theory that it becomes hard to approach a problem from any other direction.

Edit I don't mean this as an insult. I see it with a friend of mine who struggles with problem solving when not mapping to cat types

> I see it with a friend of mine who struggles with problem solving when not mapping to cat types

Yes, I remember a Dan Luu and another developer talking about something similar. The concepts like currying, composition and monads all work so smoothly in Haskell that you want to try to get them to work in other languages. It can make your code in those other languages worse because you're trying to get the language to do something it's not designed to do.

Further to that though then no one understands what you've written.

This is what Dan Luu said [0]:

> One was that I really got into functional programming and used a functional style everywhere I could. Immutability, higher-order X for any possible value of X, etc. The result was code that I could write and modify quickly that was incomprehensible to anyone but a couple of coworkers who were also into functional programming.

[0]: https://danluu.com/learning-to-program/

I know nothing about category theory. I honestly have never studied it, and don’t plan to. As far as I know, aside from the typical Haskell type classes who people say are based on category theory, beam doesn’t use any esoteric concepts. It is definitely an exercise in engineeeing, not theory.

Beam is based on the relational algebra, which is the basis of SQL. Of course, it doesn’t enable a monkey to write database queries, but it does enable engineers who understand relational algebra to do so.

If your complaint is that you have to understand relational algebra to use a relational database, then your complaint is well out of the scope of beams domain.

Also, I have no idea what you mean about your friend. We can play the personal anecdote game all day long. When I was a JavaScript developer, I saw my fellow devs constantly testing for invariants that would be trivial with Haskell. We use JavaScript at work now too and they access our database indecently. Their queries do not enjoy the advantages beam provides and we’ll be switching to using a Haskell backend service soon instead

Not sure how you would draw anything about relational algebra from my statement. I love SQL and it's relationship to relational algebra. My only major complaint with sql is the difficulty in being done DRY principles. I like its declarative nature and immediacy when you have a database connection, which is possibly related to what I like about good dynamically type language environments