Learning Haskell – Miscellaneous Enlightenments
sras.me
sras.me
That's not really why. Even if you could unwrap the IO constructor, there is no `a` inside it!
As it turns out, with you can unwrap the IO constructor if you import GHC.Types from ghc-prim:
Prelude> import GHC.Types
Prelude GHC.Types> :set -XUnboxedTuples
Prelude GHC.Types> let (IO f) = getChar
Prelude GHC.Types> :t f
f :: GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld, Char #)
What's inside is a function. You can't get the return value out of a function without running it. You can, of course, run it. `unsafePerformIO` will give you a thunk that, when forced, will do just that.I often see the sentiment on HN and other programming forums that the "magic of Haskell's mysterious and arcane type system with the bogeyman of inscrutable category theory and monads" (to exaggerate just a tad) prevents you from mixing pure and non-pure code in Haskell. That's not what's going on. It's just a clever choice by the standard library to not export certain functions that unwrap a type (or at least hide it behind a function with the word unsafe in it), a trick that is used by any language that has support for private and public functions.
Indeed this exact same thing can be replicated by any language that is expression-focused and has support for immutable bindings. Just modify your standard library to wrap everything side-effectful in an IO type and don't let users unwrap that.
That's not necessarily true with all strict evaluation. You can use seq to create an evaluation dependency between two values that need not care about ordering. If c = seq a b, the when c is evaluated, both a and b will have been evaluated, and c will evaluate to the b. But there is explicitly no ordering there. The compiler may choose to evaluate either a or b first, by whatever metrics it wants.
It takes a lot of practice to get the hang of thinking about evaluation like this. But it's the key to not having memory use problems in Haskell while also not breaking code with unnecessary strictness.
Now, if you'll excuse me, I have to write a web app that accepts this API and returns these things... and implement auth... sigh.
I’ve not had any bug reports in ages. Which is counter to what most of the teams were used to when deploying services in JavaScript or Ruby. Usually you test like hell, QA, ship, get a few error reports from users, fix them, get one or two a couple months later and fix those... then a year later you change something and get a bunch of new error reports about the feature that used to work... and you fix those.
Haskell forced me to address most of those errors before my program would compile. I had to write a few tests but orders of magnitude fewer than I was used to. I shipped fast.
I got one report from the customer many months later when I made a mistake due to a miscommunication of requirements. One test case prevented that kind of error happening again inadvertently and shipped in less than an hour. Haven’t heard any reports since.
Haskell is my go to where I can get away with it. Absolutely solid stuff.
But: you're also comparing Haskell to completely dynamic languages like Ruby or JS. There are things in the middle. Even Java lets you avoid many silly typing errors and if you use something like Kotlin (and you use it well, not just as a slightly more modern Java), you can IMHO get quite far in terms of correctness for typical web backends.
Now the power of languages like Haskell may be warranted in more complex scenarios and I don't want to claim there are no benefits to it, but there are degrees in between the madness that is JS and something like Haskell.
It wouldn't really help, of course. Business requirement drudgery is business requirement drudgery in any language.
Actually, this is something I've always wondered: I know that any Haskell enthusiast would, upon hearing someone say, "I like the ideas, but it's just too hard to program in", respond, no, it's not, you just didn't learn it the right way, or this IDE with that extension makes it much easier, or you really should have started with Learn You A Haskell. But what I'm really curious about is this: Putting all that said, assume for the moment that Haskell really is too complicated for anyone without an advanced degree in hyperbolic topology to understand.
Do you care?
I will say there's no such thing as a programmer who can't learn Haskell and be productive in it. It's not fundamentally more difficult than any other language. It's just that you have to learn to program more or less from scratch again. That initial learning curve was more work than I'd been through to learn a programming language in 25 years, when I first learned Haskell.
Of course, there's definitely such a thing as a programmer who won't like Haskell even after learning it. It's not for everyone. But neither is perl, or c, or python, or java, or....
Tbh this complexity budget is a rather stupid notion in regard to programming languages. Higher level languages allow you to spend less cognition on the language provide you actually know the language. There's a very clear reason we are moving away from C to more complex languages.
C++ destructors and rvalues help condense ownership without having to think about the execution path of a whole program.
I'm not aware of what haskell features + tools pragmatically decrease the complexity of a program. If an experienced programmer is still fighting with the language heavily after 9 months and can't figure out a good way to debug programs, that should be a red flag if it is a consistent scenario.
Haskell can be learned in a couple of months of serious learning. If you don't get it after 9 months you simply weren't serious in learning it. It's not like Haskell is harder then any other language. It's concepts are different which makes it hard to learn. But C++ and Python are much harder to write code in then Haskell.
That seems a bit harsh. I can believe that everyone should be able to learn Haskell sufficiently well after a couple of months if they stumble across the correct learning material and have sufficient support. I can also see that someone from outside the community might make a solid effort for nine months and not make much progress, simply because the correct learning material wasn't easily discoverable.
haskell has a long history, and ancestors with a long history too, it's normal to feel alienated when you have a background with mainstream languages
I can't talk for haskellers (I'm not using it) but it's not that FP/haskell doesn't care, it's just that its medicine taste sour to you.
If I can give you another point of view, languages like php, started very differently from what they are now. Give a 'closure' to a php3 dev and he will feel just like you do I believe. In 2020, the most used php web frameworks use closures as the normal way, and people are quite happy with it.
I believe haskell is just like that, it's just too advanced.
Do people hire experienced imperative programmers and train them to use languages like Haskell?
Probably many of the same reasons Haskel is not yet a thriving mainstream language.
90% of problem domains yield well to procedural/hybrid languages.
The rest could stand the additional rigor and even provability possible with pure FP languages.
class Convert a b
requires MultiParamTypeclasses