Show HN: IHP, a batteries-included web framework built on Haskell and Nix
ihp.digitallyinduced.com
ihp.digitallyinduced.com
> Back in the early days of the web, when server-side rendering was still a thing, javascript was sprinkled here and there to make a few parts of your web app just a little bit smoother.
It's "built on top of Haskell and Nix."
The more detailed 20 minute introduction and documentation is located at: https://ihp.digitallyinduced.com/Guide/ I think the "recipes" section provides some illuminating examples.
The creators make the following claims about durability at the end of their introduction page:
> Lots of frameworks are already gone a year after launch. Especially in the fast moving JS world. But don't worry about IHP. We have been using it at digitally induced since 2017. It's actively used by us and our friends and partners. Even without external contributors we will build new features and do periodic maintenance releases in the future. We have big plans for IHP and as a profitable and independent software company we have the ability to actually execute them over the longterm.
I'm very skeptical of web frameworks / toolkits. While I only work on personal projects, I tend to try to use pure HTML first, then add CSS where needed, then add JS where needed, then add backend where needed - always striving to minimize the amount of the next layer. This project seems to be targeted to someone with my preferences.
I'll definitely be keeping an eye on it, and poking around with it.
This was a good reminder that I should at least skim the article first.
On the other hand I wonder if there's a way for HN/Reddit to help people write summaries in comments. (Perhaps even recursively!)
Working in similar space[1], I have been talking to many early customers. Right from somebody who knows enough programming to product managers to CTOs, the idea of having a GUI within web framework and to have CRUD APIs ready with just few clicks gives them an amazing head start in building web apps. Getting past this redundant phase of creating basic CRUD with no hassle means - they can devote their energies on the business side of things. It will not be wrong to imagine in few years this workflow will become a norm.
I hope so too but we had this in different forms since the early 80s already (maybe earlier) and it never got big for some reason.
Could you name them, happy to check them out.
IHP is supposed to become the Django/Rails/Phoenix of Haskell.
I've been using Django professionally for since 2013, but have started using IHP a couple of weeks ago. It's still quite early but with surprisingly few rough edges, i.e. the developer ergonomics are much better than I expected. It has great documentation that is improving rapidly (as opposed to many other Haskell libraries, which provide little more than API docs or even just the typed function definitions) and offers a refreshing take on database management and migrations.
Some of its killer features:
- HSX, a JSX-like template language that looks like HTML while providing type safety
- Auto live reloading without the need to setup anything
- Documentation with examples: it lets you query the database without learning about monads
- it defines |> for you ;-)
- type-safe, composable SQL queries:
projects <- query @Project
|> filterWhere (#userId, userId)
|> filterWhere (#deleted, False)
|> orderBy #createdAt
|> fetchI wonder if the person who wrote this understands SQL to sufficient depth. Not saying either way, just asking.
Regarding b), yes there are good reasons for prepared statements. I won't go into your argument "for scalability" (premature optimization cough) but cached query plans aren't perfect either: data and data typologies change, and so does the optimal query plan. See https://blog.soykaf.com/post/postgresql-elixir-troubles/ for a blog post about Elixir/Phoenix/Ecto users being bitten by that.
> I wonder if the person who wrote this understands SQL to sufficient depth. Not saying either way, just asking.
I did not write the IHP code, just the above comment. But I've read many of CJ Date's books and have a good grasp on the relational model, and of SQL too. I simply don't see things as black/white, there are certain queries where I do prefer prepared statements and functions, or PL/pgSQL even, then there are ones where I use an external .sql file to keep things tidy. But most of the time (especially in the user facing part of a web app) I like my ORMs or SQL DSLs.
Using type hints would also protect you from using variables with incompatible types with a better designed API (Django's ORM API is anything but).
As for SQL performance, I've usually only worked with up to hundreds of millions of rows per table, and the most important thing at that scale was to attempt to keep indexes in memory cache (that improves or degrades the performance by a couple of orders of magnitude). I haven't had a need for query plans to be cached, though I did use subselects to force particular query plans when needed (which has the similar problem of query plans not being the most efficient ones when data evolves sufficiently).
The choice isn't to use dynamic SQL or not in these cases, it's whether you implement the feature that requires dynamic SQL or leave it out entirely.
And like these other server-side web frameworks, IHP is SQL centric. What sets it apart is the IDE integrated into the dev server. The IDE together with Nix allows IHP to be PostgreSQL only, avoiding out-of-band server installs and providing a UI for schema/model construction.
This is an interesting option and seems to have appeal beyond Haskell enthusiasts.
Using PostgreSQL in the development environment for say Rails or Django requires "out-of-band" installation, configuration, and management. Frameworks like Rails and IHP apply the schema/migrations to a live development RDBMS and read the Catalog Metadata to generate the classes/structs used as the Data Access Objects (e.g. ActiveRecord in Rails). The RDBMS, therefore, is part of the CI/CD pipeline.
Other ORMs define their entities independent of the RDBMS. I think Java JPA and Apple Core Data work this way; the SQL DDL is generated from the Entity Model. YeSQL-style frameworks also require a live development RDBMS but they extract metadata from each prepared statement rather than catalog metadata for each table which is mapped to a class/struct.
Edit: Gah. :)
Anyway in my particular case if I had any project that was a good fit for server side rendering I would probably now go with php and some libraries but probably no framework. I've been looking at some "weirdly coded 90's style php projects". An while the code is a terrible mess there's also the magic that I can read everything that's happening pretty quickly because it's just there or in a file next to it and not hidden in a library and a sub-library with calls to functions that I never seen before.
seriously? 2020 and you'd pick php for a greenfield project?
and you mention this here, where we're discussing a project that provides: strong typing, typed safe queries, type safe templates, and more.
interesting.
But it depends on what you are doing ofcourse.
Exactly, this is a real reason for not using the technologically superior.
If these other languages were better in a holistic sense, businesses would switch.
I would argue against the "technically superior" position on three merits:
1. Finance, 2. Median productivity 3. Long-term product stability
Network effects mean that familiar languages will dominate. PHP, C#, and Javascript are familiar.
PHP has had staying power because it is extremely well-documented (with examples) for the novice, prioritizes backwards compatibility, and is reasonably if not very productive for most developers. The documentation section of PHP.net is probably the most important language "feature" of PHP - it trumps almost any language design feature you think is important.
It reads easily. It's easy to implement. It interacts natively with JSON in a completely fluid way. The database handling routines are rock solid and fast. The core language team spends a lot time improving the safety and performance of existing code. There's a good debug story.
It's its own templating language - no need to bolt on a hand-rolled templating mechanism. Just PHP all the way down. It prioritizes language features (reflection) that make writing libraries and frameworks easier. It promotes building reusable tools. Important features are pulled directly into the runtime, based on popularity in the ecosystem. The kitchen sink is included and it's portable.
Basically, it's a language that has been developed by people who actually have to build and maintain projects over a long period of time. A useful language is more than it's design.
I see the other side: it's a sinking ship. FB comes to rescue PHP, but internally seems to like anything but PHP for greenfield projects: Java, C++, Erlang (chat msg broker), OCaml/Reason (messenger.com app), even Haskell is used for some spam filtering tool.
So now we just mostly deliver things in old, boring but very standard tech. Using almost written by us and definitely no custom low level stuff like we used to. Because we did all that work before, we know how to optimise for performance everywhere, how to optimise dbs, how to optimise frameworks and webservers. We do everything according to the standards and best practices; now we know that we can get people in 20 years to work on our code. But it is much much slower at the start; so much setup and plumbing. Very boring and tedious. I guess that's the point.
In relation to PHP, really? Sure it has come a long way recently, but there's too much still in there that can never be fixed.
I dont think what IHP delivers is some sort of "fashion": they choose to be server-side only, pretty old school. The typing discipline is not very fashionable either: old, time tested, established, but not often leveraged for the development of simple websites/webapps.
PHP 8 is due to be released this fall which improves the situation even more.
Symfone is the web framework that had the highest count of contributions over all frameworks in all languages.
The PHP community took a 180 degree turn from the 90's style flat files with a mix of HTML, SQL and code in the last decade. That times are gone (of course that kind of code is still laying around)
For someone who already knows PHP, starting a project in 2020/2021 in PHP is an excellent choice.
I had the same! Then I invested in learning some Haskell/ Elm/ Reason/ Rust/ Kotlin: it changed my preferences for ever. I now look for proper sum types and (pattern) matchers, strong typing discipline and null safety.
While PHP is still a joke compared to even Java which it very hard tries to become (which I think is a good thing), for someone who only knew PHP the entire time, the situation still got much, much better over the last decade...
Almost no one is solving FANG problems, and people literally throw their clients/businesses money away on poor value because they've lost focus on what's important: delivering a solution for what they need right now, not what you want to spend your time playing with.
Also what is the big deal with type safe templates when you're literally just abstracting building HTML strings?
I've heard you can combine React with Symfony, which sounds really cool.
React is not a language. TypeScript is very close to PHP, both in imperativeness, in OO-ness, in did-not-initially-support-it-but-sometimes-added-it-later-but-now-its-a-mess-ness, in BW-compatible-ness, in quirkiness.
I know React is not a language, but I listed the whole stack to compare it to IHP, which seems to try to combine everything. Which is good! I’d love a Django/RoR esque Haskell platform.
There are a whole bunch of options between those two extremes and I can’t for the life of me think why people don’t talk about them more often.
For example, I think the new Hey.com implementation hasn’t received anywhere near the level of recognition that it probably should have.
It’s an entire email application with a single set of screens that power all web, desktop and mobile apps, does so with all the speed of an SPA, has no need for advanced state management, has the ability to push live updates on a per component basis on any screen and does it all in under 40kb of JavaScript.
Seriously go and look at the source code. I’ve only seen a tiny number of people talking about it like in this post https://dev.to/borama/a-few-sneak-peeks-into-hey-com-technol...
But to me the past few years of SPAs are starting to look more and more like a mistake to me where they became the rule when they should have probably been the exception.
There is a second library that they have used along side that for handling all of the app specific JavaScript here as well https://stimulusjs.org/
The benefit of building with a de-coupled JS frontend (SPA) and an API is that it can extended and adapted far easier than using server-delivered HTML.
If you have an API that delivers JSON/Protobuf/whatever, you can easily make new interfaces to that backend. If you are currently delivering a web app in HTML/JS, but decide you want a native Mac/iOS app written in Swift, you'll just end up building an API anyway.
Sure, there are plenty of websites that wont ever need additional interfaces, but if your goal is to make an app that can easily have new interfaces added to the mix, de-coupling is the way to start in my opinion.
This approach and separation of concerns also means that building e.g. REST or GraphQL APIs on top of your application is simple, as your web framework has no say in how the data is actually structured or queried.
I think there is a heavy if unconscious bias among web developers now that the “one true way” to build web apps is to take the same methodologies and frameworks from Facebook and Google usually.
I’m obviously not the first person to point this out but trying to replicate the software development processes of some of the largest companies in the world is in no way correlated with a better anything (user experience, dev experience, code, time to market etc).
In fact I would take it further and say that there are a not insignificant number of new developers especially from the dev boot camp style pipelines who literally don’t even know how to build anything without reaching for one of these tools. We saw the same thing with people reaching for Bootstrap or now Tailwind for a long time and not knowing how to do anything outside of it. This isn’t to give them a hard time, I have been that kind of Stack overflow driven developer myself for a long time. I just think that maybe as an industry we have made some poor choices that have become gospel overtime and it might be worth revisiting that.
Remember when everyone thought NoSQL was a good idea and wanted to get rid of their relational DBs? Nobody remembered _why_ we went to relational DBs until after all of their data was duplicated and inconsistent in NoSQL solutions.
I think the root of this is a lack of appreciation for or lack of knowledge of the history of software engineering.
I wasn't able to find anything on deployment in the docs. What does it look like?
I've been looking for a framework with the following requirements:
- Functional-ish language
- Statically typed with Result<T, E> error handling.
- Garbage collected.
- Compile time checked HTML templates, with autoformatter and IDE support (like working with JSX/TSX in VS Code).
- Some kind of SQL DSL that has decent IDE support (like Ecto on Elixir, Diesel on Rust).
This framework checks off more of those than any framework I've seen. I'll definitely be giving it a try.I’ve been playing around with Phoenix recently and I’ve been missing a decent type system (Dialyzer is pretty bad). I know very little Haskell but this makes me want to dip my toes in.
I always thought it is better to mix client/server rendering; the 'everything client' or 'everything server' both do not work for a large number of applications. So why not mix them. Unfortunately not much out there battery-included that consistently supports that model.
I did not dive into IHP (I heard about it as the RoR for Haskell) but, after reading the introduction, I'm probably going to get depressed when I hear how you do the inevitable client-side stuff here; there is a really good opportunity to mix them as there is HSX and you can compile Haskell to JS. So there should be an opportunity to appoint, where supported, some (parts of) a page as serverside/clientside.
We have been tinkering a bit with building something close to Phoenix LiveView with HSX. Hope we can show something in that direction later this year.
May I suggest you have a look at Next.js. It lets you solve this in a very ergonomic way. Maybe even for your existing project.
Thanks for Next.js: I did not know it.
I like the neat UI, auto refresh and everything. I even skimmed the 27-minute demo video (that's a bit long guys), but I don't see any reference to testing, making this a nonstarter for me.
I'd love to see a guide on integrating with webpack or any frontend tech in the stack.
I like how your code generation seems to expose most of the structure for customization, but have you thought about having different customizable templates for code generation? Like generating just REST API for this table vs generating user visible views.
But would IHP work in Windows natively? AFAICT, Nix doesn't work in Windows unless you use WSL(and even here I'm not sure how smooth it is).
What's it like to debug when something goes wrong?