Instead this will put all browsers on a much more even playing field, and perhaps it will force governments and citizens to realise that free software takes someone to write it.
1,236 karma · joined May 5, 2014
Instead this will put all browsers on a much more even playing field, and perhaps it will force governments and citizens to realise that free software takes someone to write it.
Any paradigm shift requires re-learning I think. I don't actually think that's particularly hard, nor do I think it means the paradigm isn't a good one, it's just an inevitable consequence of a paradigm shift. Some shifts are easier than others, if the paradigms are closer together, but functional and imperative programming are quite distant in my view.
Nevertheless, I've seen some people find this easy, others find it hard. YMMV I guess.
This just seems like bad libraries, I'd agree that this is bad and sort of defeats the point. I haven't actually encountered this with any libraries I've used, and we tend to avoid MonadThrow / Catch except in particular circumstances.
> in this case, I'm worse off than in Golang.
Having (unfortunately) had to write some Golang, I don't think this is true -- I've encountered plenty of code in Golang in which it seems idiomatic to return things like empty strings and empty objects instead of error values which, I think, it's still possible to mishandle.
Perhaps this can be summarised as: you can still write bad Haskell, but I don't think it's particularly idiomatic looking at the libraries I've spent most of my time using, and the machinery you are provided allows you to do much, much better.
So my original intent with that paragraph was very different, but you're right that I was not very precise with some of those statements.
Thanks for taking the time to explain, you've definitely helped expand the way I've thought about this.
> computability and programming just aren’t that related
I … don’t think I understand
Mostly because while I found of the tooling occasionally difficult, I didn’t find Haskell particularly bad compared to other language ecosystems I’ve played with, with the exception of Rust, for which the compiler errors are really good.
> The syntax summary in the article is really good
Thanks, I wasn’t so sure how to balance that bit.
For the "hello world" webserver, this might be a bit instructive: https://github.com/gfarrell/gtf.io/blob/main/src/GTF/Router....
In this syntax note, I was not trying to teach someone to write Haskell programmes, but rather to give them just enough to understand the examples in the essay. I did test it on a couple of friends to see if it gave them enough to read the examples with, but was trying to balance the aim with not making this section a complete explainer (which would have been too long).
Perhaps I got the balance wrong, which is fair enough, but I don't think it's required to define _every single_ term upfront. It's also not crucial to the rest of the essay, so "The article lost me at following sentence" feels a bit churlish.
This is what I was talking about in the section "Unlearning and relearning". While there are _some_ domains (like embedded systems) for which Haskell is a poor fit, a lot of the difficulties people have with it (and with FP in general) is that they have been heavily educated to think in a particular way about computation. That's an accident of history, rather than any fundamental issue with the programming paradigm.
In the essay, I didn't say "Haskell is the only thing you should use", what I said was:
> Many languages have bits of these features, but only a few have all of them, and, of those languages (others include Idris, Agda, and Lean), Haskell is the most mature, and therefore has the largest ecosystem.
On this:
> It's not bleeding edge any more.
"Bleeding edge" is certainly not something I've used as a benefit in this essay, so not really sure where this comes from (unless you're not actually responding to the linked essay itself, but rather to ... something else?).
Yes, it does: `bar` in your example is an `Int`, it has no arguments. That is captured precisely in the type signature, so I'm not sure what you're trying to say.
This part: "the type information only tells you how you can use doSomething. To know what is doSomething, you actually have to read the code :\" I think we're disagreeing on something quite fundamental here, based on "it doesn't tell you that bar depends on foo, and on foo's type. Also you have to read the body of bar, and also it is bad for code reuse."
(Although I am certainly open to the idea that "[I] failed to demonstrate it".)
A few things come up here:
1. Firstly, this whole example was to show that in languages which rely on this goto paradigm of error handling (like raising exceptions in python) it's impossible to know what result you will get from an expression. The Haskell example is supposed to demonstrate (and I think it _does_ demonstrate it) that with the right types, you can precisely and totally capture the result of an expression of computation.
2. I don't think it's true to say that (if I've understood you correctly) having functions call each other is bad for code re-use. At some point you're always going to call something else, and I don't think it makes sense to totally capture this in the type signature. I just don't see how this could work in any reasonable sense without making every single function call have it's own effect type, which you would list at the top level of any computation.
3. In Haskell, functions are pure, so actually you do know exactly what doSomething consumes, and it doesn't matter what getResult consumes or doesn't because that is totally circumscribed by the result type of doSomething. This might be a problem in impure languages, but I do not think it is a problem in Haskell.
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.
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_.
I actually really like the syntax as it makes it easy to write DSLs which are actually just Haskell functions.
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.
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?
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.
1: https://specifications.freedesktop.org/basedir-spec/basedir-...
I was going to make a similar comment -- it seems there might not be well agreed definitions of "expressiveness" here. I write most of my own projects in Haskell, precisely because I find Haskell to be extremely expressive, but I mean something different to "reads like English" (for which I think AppleScript is the closest example I can think of): to me, the expressiveness of the language is "how accurately can I describe my problem domain to the computer in a way that lets me naturally reason about it in code". I think this is mostly a function of the type system, not the particular syntax (e.g. allowing "?" in a method).
I am really interested in what other people consider "expressiveness" to mean, however.