Hacker News new | past | comments | ask | show | jobs | submit | more gtf21's comments login

> - how easy is it to make a web application with a hello world endpoint?

If that's all you want it to do, it's very easy with Wai/Warp.

> - How easy is it to auth a JWT?

We don't use JWTs, but we did look at it and Servant (which is a library for building HTTP APIs) has built in functionality for them.

> - Is there a good ORM that supports migrations?

There are several with quite interesting properties. Some (like persistent) do automatic migrations based on your schema definitions. Others you have to write migration SQL/other DSL.

> - Do I have to remodel half my type system because a product owner told me about this weird business logic edge case we have to deal with?

I think that's going to really depend on how you have structured your domain model, it's not a language question as much as a design question.

> - How do I do logging?

We use a library called Katip for logging, but there are others which are simpler. You can also just print to stdout if you want to.


Thank you! What I was more saying was that an article like this would do better showing some practical simple examples, that would let people do things, rather than bemoaning how Haskell is viewed in 2024.


Oh! I hope I wasn't bemoaning too much -- that was the lead-in, but it's mostly about what I really like about the language (and had some examples but I also didn't want to write a tutorial).


For reference (in case it's helpful), my website (where this essay is hosted) is written in Haskell and is basically a fairly simple webserver.

For the "hello world" webserver, this might be a bit instructive: https://github.com/gfarrell/gtf.io/blob/main/src/GTF/Router....


thank you for the repo, I've been wanting to learn haskell but I didn't really know what can I build with, i might as well build some similar things like this since I've been trying to make my own blog server, now i get a chance to learn haskell and finally get up and build this.


There is also [Learn Haskell by building a blog generator](https://learn-haskell.blog/) - that might be interesting to you.


We do use other ecosystems, yes. I haven't really found the tooling for Haskell to be particularly obstructive compared to other languages. I've run into plenty of mysteries in the typescript, python, ObjC/Swift, etc. ecosystems that have been just as irritating (sometimes much more irritating), and generally find that while HLS can be a bit janky, GHC is very good and I spend less time scratching my head looking at a piece of code that should work but does something wild than in other languages.


> so that compilers can reason about it

Actually this is the wrong takeaway, I think it's so that programmers can reason about it.

This isn't about type errors, it's about precisely describing a particular computational expression. In the python example, it's very unclear what `do_something` actually _does_.


You can have that syntax if you want it via `OverloadedRecordDot`.

I actually really like the syntax as it makes it easy to write DSLs which are actually just Haskell functions.


> The library ecosystem is probably the biggest issue.

I'd love to know which things specifically you're thinking about. For what we've been building, the "integration" libraries for postgres, AWS, etc. have been fine for us, likewise HTTP libraries (e.g. Servant) have been great.

I haven't _yet_ encountered a library problem, so am just very curious.


A few years ago I tried to use Servant to make a CAS[0] implementation for an academic project.

One issue I ran into was that Servant didn't have a proper way of overriding content negotiation: the CAS protocol specified a "?format=json" / "?format=xml" parameter, but Servant had no proper way of overriding its automatic content negotiation - which is baked deeply into its type system. I believe at the time I came across an ancient bug report which concluded that it was an "open research question" which would require "probably a complete rework".

Another issue was that Servant doesn't have proper integrated error handling. The library is designed around returning a 200 response, and provides a lot of tooling to make that easy and safe. However, I noticed that at the time its design essentially completely ignored failures! Your best option was basically a `Maybe SomeResponseType` which in the `None` case gave a 200 response with a "{'status': 'error'}" content. There was a similar years-old bug report for this issue, which is quite worrying considering it's not exactly rocket science, and pretty much every single web developer is going to run into it.

All of this gave a feeling of a very rough and unfinished library, whose author was more concerned about writing a research paper than actually making useful software. Luckily those issues had no real-world implication for me, as I was only a student losing a few days on some minor project. But if I were to come across this during professional software development I'd be seriously pissed, and probably write off the entire ecosystem: if this is what I can expect from "great" libraries, what does the average ones look like - am I going to have to write every single trivial thing from scratch?

I really love the core language of Haskell, but after running into issues like these a few dozen times I unfortunately have trouble justifying using it to myself. Maybe Haskell will be great five or ten years from now, but in its current state I fear it is probably best to use something else.

[0]: https://en.wikipedia.org/wiki/Central_Authentication_Service


> Your best option was basically a `Maybe SomeResponseType` which in the `None` case gave a 200 response with a "{'status': 'error'}" content.

This seems to be an area where my tastes diverge from the mainstream, but I'm not a fan of folding errors together. I'd rather a http status code only correspond to the actual http transport part, and if an API hosted there has an error to tell me, that should be layered on top.


Well, that's why errors have categories:

HTTP status ranges in a nutshell:

1xx: hold on

2xx: here you go

3xx: go away

4xx: you fucked up

5xx: I fucked up

(https://x.com/stevelosh/status/372740571749572610)


At work we had to do both of these things and it is possible if im remembering correctly.


I tried building a couple small projects to get familiar with the language.

One project did a bunch of calculation based on geolocation and geometry. I needed to output graphs and after looking around, reached for gnuplot. Turns out, it’s a wrapper around a system call to launch gnuplot in a child process. There is no handle returned so you can never know when the plot is done. If you exit as soon as the call returns, you get to race gnuplot to the temp file that gets automatically cleaned up by your process. The only way to eliminate the race is by sleeping… so if you add more plots, make sure you increase your sleep time too. :-/

Another utility was a network oriented daemon. I needed to capture packets and then run commands based on them… so I reached for pcap. It uses old bindings (which is fine) and doesn’t expose the socket or any way to set options for the socket. Long story short, it never worked. I looked at the various other interfaces around pcap but there was always a significant deficiency of some kind for my use case.

Now, I’m not a seasoned Haskell programmer by any means and it’s possible I am just missing out on something fundamental. However, it really looks to me like someone did a quick hack that worked for a very specific use-case for both of these libraries.

The language is cool but I’ve definitely struggled with libraries.


The project was a cloud agnostic platform-as-a-service for building healthcare applications. It needed graph-DBs, Postgres, all clouds, localisation, event-streams, UIs, etc. I won't list where the problems were, because I don't think it's helpful -- each project has its own needs, you may well be lucky where we were not. Certainly the project wasn't a standard enterprise app, it was much more complex, so we had some foundational things we needed that perhaps your average dev doesn't need. However, other ecosystems would usually have a decent off-the-shelf versions, because they're more mature/evolved.

You have to realise that none of the problems were insurmountable, I had a talented team who could overcome any of the issues, it just became like walking through treacle trying to get moving.

And yes, Servant was great, we used that also. Although we didn't get super far in testing its range.


Probably referring to something like spring (for java), which is a one stop shop for everything, including things like integration with monitoring/analytics, rate-limiting, etc


Spring is probably the worst framework created, so I wouldn't list that as an example :/


> Granted, the tooling is sh*t.

I hear this a lot, but am curious about two things: (a) which bit(s) of the toolchain are you thinking about specifically -- I know HLS can be quite janky but I haven't really been blocked by any tooling problems myself; (b) have you done much Haskell in production recently -- i.e. is this scar tissue from some ago or have you tried the toolchain recently and still found it to be lacking?


Everytime I use cabal and/or stack, it gives me a wall of errors and i just reinstall everyrhing all the time.


And if you share stack transcripts I’ll look into those for you.

I’ve experienced this too, the tools can certainly be improved, but also a little more understanding of what they do and how to interpret their error messages could help you (I am guessing).


If you share a transcript from a cabal session I'll look into this for you.


I think there are more fundamental differences between functional and imperative programming paradigms (or, perhaps, declarative and imperative programming styles?) than between passing by reference and passing by value (after all, variables are just references, filesystems have links, it just doesn't seem that unfamiliar).

I have definitely seen people struggle to wrap their head around declaring expressions representing what they want to compute when they are very used to imperative control flow like mutating some state while iterating through a loop.

> Kind of reminds me of a sect that promises you great things if only you work hard on leaving all your prior life behind.

I think this is sort of saying "hey this one thing looks like this other thing I don't like, therefore it must carry all the same problems". Perhaps we can call it "the duck type fallacy", but I don't think it's true to say that "anything which tries to change paradigm" is equivalent to cults.


> after all, variables are just references

That's the whole point of Rust, that they are not that. They are named, sized memory slots that values can be moved into or moved out of.

> I have definitely seen people struggle to wrap their head around ...

The struggle comes from being forced to use recursion where it doesn't make things easier to express but harder. Then they remember it all compiles down to machine code that just uses iteration fueled by bare metal equivalent of goto-s and the struggle feels pointless.

Imagine somebody took away your stack so when you want to do recursion, you'd be forced to roll your own stack every time. You'd struggle too.


> definitely seen people struggle to wrap their head around...

I think it's a top-down vs bottoms-up approach to solving a problem.

Most people actually think in terms of top-down. They break a problem down into smaller sub-problems, which they then either break down more or has done sufficient breaking down to solve it.

I think functional style of thinking would make you do a bottoms-up approach to problem solving. You will create a very small solution (function) to solve a very trivial version/type of the problem, then repeat for each small thing. Once you have sufficient number of basic functions written, you can assemble them into solving a bigger problem.


You can take either approach in nearly any other programming language. I disagree that functional programming has any particular advantage here.


"Diagrams as Code" has been around a long time (e.g. DOT), not sure what this is really bringing as an improvement, especially as seems to require an account (at least it does when I click "get started" and, as someone else points out, is closed source.


The npm package is free to use, but closed source until I have bandwidth.

To be clear, you don’t need an account to use the npm package which has all of the functionality to perform layout and rendering. An account is only needed if you want to sync the graph and have a web page to view renderings. This is useful if you’ve instrumented a long lived application with Vizdom, but don’t want to produce a local layout/rendered image because you can’t really “view” it if the service is running in the cloud.


an account. to make a diagram. sigh diagrams-as-a-service. sign. "turn your OCD side project into a business: turn something that people do for free and don't really care that much about into a paid subscription service because..."


This seems unjustified. If people want it, they'll buy it. If not, no harm done. If you could e.g. embed the diagrams into Confluence pages, that's something people will definitely pay for.


I don't think its even OCD side project its just a contrived "how 2 make saas business?"


Ah ok thanks for clarifying!


Looks like this uses DOT? Click on "Editor" at the top


I wrote some functionality to parse DOT to feed it into the layout engine before I got everything working. It was a great way to validate more complex graphs with a DSL that is already prevalent. So for now it’s only present in the webapp.

DOT parsing isn’t part of the npm package, but I’m not totally opposed to include it! It may add 1-2Mb more to the wasm bundle.


> So for now it’s only present in the webapp.

Just so you know, I find this terribly confusing. You see the homepage with your code, then you think "oh, I'll try this editor here..." and then it turns out it's Dot? All examples are written in Dot? Why? Didn't it say "no DSLs"? Didn't it show some TypeScript in the homepage?

It can very easily make people get the wrong idea about what your project is.


TBBQF I have no idea what the value proposition of this project is actually supposed to be.

Edit: It seems to have almost 100% feature overlap with graphviz, but it is a paid SaaS? I don't get it...

Edit 2: This has to be a troll post. "Up to 3 graphs" for free --are you kidding me? I can run `dot` a million times in a second for free


Yeah I’ll admit, that isn’t clear. I used DOT to test it a while back and opened that up for folks who also wanted to mess with DOT, but that isn’t the value prop today.

You can create and render as many graphs as you like with the package offline - only the real-time sync is limited.


> You can create and render as many graphs as you like with the package offline - only the real-time sync is limited.

Why wouldn't I just use graphviz then?


You know what? You’re right! That’s confusing. I’ll try and make it better.

Really good feedback and I’m being serious. Wish I saw that earlier.


Some comments have already covered the subcommands thing, but why are you using the XDG_CONFIG_HOME directory `~/.config/wrm` to store files? This should be for _configuration_ not _state_. You should follow the specification for XDG base directories for this [1] which would suggest you put the trash in `~/.local/share/wrm/trash`

1: https://specifications.freedesktop.org/basedir-spec/basedir-...


Thank you!. I'll change it soon.


I've continually been dragged back into the operational weeds of the business over the last few years (by which I mean things like running a team day-to-day, working through risk analyses on a project, etc.). This is (a) not something I enjoy; and (b) not the thing I'm best at (although I am quite good at it for short periods). I'd really like to be spending my time on things I get satisfaction from beyond "you're making your company work so that should be satisfying in itself", so this year one of my goals (sooner rather than later) is to actually make myself as operationally redundant as possible so I can have higher leverage and enjoy it at the same time.


Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: