Live data from Hacker News

Leaving Haskell behind

journal.infinitenegativeutility.com

341–350 of 402 posts

Re: Leaving Haskell behind

#341

Earlier quoted context omitted.

Perhaps, but what you may not understand is that not ALL developers _want_ a purely functional language. For some, things like Kotlin hit a sweet-spot. One can lean a bit more into a functional style, or they can lean more into an OO style and it's acceptable. Some are very interested in thinking in terms of Functors, Applicatives, Readers, etc... some just want map/filter/reduce. That's what the Streams API did for…

Kotlin doesn't get enough love. It gets derided by some Java developers for being too cutesy and sugary and it's not talked much about by the kinds of people who love to talk about Haskell, Lisp or Rust (no shade to these languages), but to me it's the most pragmatic language I've used so far.

I really liked Kotlin in the beginning, but it's error handling story is non-existent. They removed the ONLY decent (not great, very flawed) complier validated method for error handling, checked exceptions, and gave us nothing in return.

It'd be so easy to simply do exactly what Rust does. Kotlin already has the ADT stuff necessary, all we need is some kind of "bubbling" operator, like the ? in Rust. Because right now, it's all just super horrible manual checks everywhere.

Re: Leaving Haskell behind

#342

As someone who uses a lot of "core" Java (ie not the messy ecosystem), and gets a lot of really complex stuff done with it, I read these articles about high-tech language features like algebraic data types and ultra-strict typing, and I think, what are these people actually doing ? The vast majority of software engineering consists of simple operations that move data from one place to another - from a DB to a JSON fi…

> gets a lot of really complex stuff done with it ... The vast majority of software engineering consists of simple operations that move data from one place to another - from a DB to a JSON file, from a REST endpoint to a browser screen

Is the complex stuff you get done with Java the same as the "majority of software engineering" you describe? I'm having trouble reconciling those two claims ...

Re: Leaving Haskell behind

#343

As someone who uses a lot of "core" Java (ie not the messy ecosystem), and gets a lot of really complex stuff done with it, I read these articles about high-tech language features like algebraic data types and ultra-strict typing, and I think, what are these people actually doing ? The vast majority of software engineering consists of simple operations that move data from one place to another - from a DB to a JSON fi…

Obviously ADTs are probably just a standin, but I think they are a feature absolutely every language ever should have. They are also not very expensive, esp. runtime wise they're (afaik) equivalent to the clunkier solutions (like classic enums).

Have you never had a thing that could be EXACTLY one of two things, ever? And you wanted the compiler to make sure that, anywhere you used that thing, you had to take care of BOTH of those possibilities? That's one of the main uses of ADTs.

Re: Leaving Haskell behind

#344

As someone who uses a lot of "core" Java (ie not the messy ecosystem), and gets a lot of really complex stuff done with it, I read these articles about high-tech language features like algebraic data types and ultra-strict typing, and I think, what are these people actually doing ? The vast majority of software engineering consists of simple operations that move data from one place to another - from a DB to a JSON fi…

Really complex stuff like moving data from one place to another? That's trivial.

Re: Leaving Haskell behind

#345
post #334
post #256

Earlier quoted context omitted.

> I still don't understand why this is necessary. Why must code compiled with GHC 9.6 use base version 4.18.0.0? Why should the binary that is GHC care about which version of the Data.List module the code that it compiles uses? Because the underlying data types might be different, so if different libraries linking to different `base` implementations pass each other instances of `Data.List`. Imagine for example a Data…

I'm not suggesting that my library should be able to transitively depend on multiple versions of base. I'm suggesting that which version of base my library depends on should not be tied to what the GHC version (used to build my library) depends on — unless my library is using the GHC-specific stuff in base.

Oh yeah, I think that's just a convenience thing. New versions of base probably use new features of GHC, so you'd end up with a backwards compatibility matrix. People would get angry either way, and I guess it's more convenient to not put in the work and just have people angry all the time so no one can say they've been misled about GHC's stability.

Re: Leaving Haskell behind

#346
post #42

Earlier quoted context omitted.

I wonder why this discussion about tooling does not include .NET languages or Swift, even if the first class tooling are IDEs such as Visual Studio or Xcode. Most probably because the open source world escapes big tech dependencies?

Linux

Yes, but you can run both in Linux natively.

Re: Leaving Haskell behind

#347
I tried to make Haskell work as a product language for a long time - and, until Rust was around, there was really nothing better than Haskell in terms of guarantees.

Haskell is a research language: it's supposed to change and experiment with new things; the permanent in-flux state is by design albeit I wish we crystallised more of the good PRAGMAs as default.

Re: Leaving Haskell behind

#348

Earlier quoted context omitted.

Perhaps, but what you may not understand is that not ALL developers _want_ a purely functional language. For some, things like Kotlin hit a sweet-spot. One can lean a bit more into a functional style, or they can lean more into an OO style and it's acceptable. Some are very interested in thinking in terms of Functors, Applicatives, Readers, etc... some just want map/filter/reduce. That's what the Streams API did for…

As someone that has done some Haskell, and does Java for a living, I think their metaphor is extremely accurate. It's not about purity, it's about how the functional parts were grafted onto the language, and therefore don"t "interop" with the classical ways very well. In a good mixed paradim language like Rust, you can freely choose the correct paradigm for the problem, and can easily mix them. In Java, they are ofte…

This is a very solid counterpoint to my argument. The no throw in a lambda is a fairly nasty wart and should have been handled in a more conformant way.

Re: Leaving Haskell behind

#349

Earlier quoted context omitted.

You should generally be writing code against typeclasses, not a particular monad transformer stack. For example: fibonacci :: MonadState (Int, Int, Int) m => m Int fibonacci = do (prev, prev2, n) 0 then put (prev + prev2, prev, n - 1) >> fibonacci else return prev2 concreteFib :: ReaderT String (StateT (Int, Int, Int) (ExceptT String Identity)) Int concreteFib = fibonacci

You misunderstand my problem. Add a logger to that fibonacci function. Potentially EVERY usage site now has to change, maybe even multiple layers. Adding a log in most languages is a local transformation. In Haskell it isn't, it can have codebase wide consequences.

That's because most languages allow arbitrary IO in all functions. You can achieve this in Haskell too if you want, by just using IO as your monad everywhere.

But most people don't do that because then it becomes really hard to reason about your code, so spending the extra time propagating a MonadLog constraint up your stack is actually worth it.

Re: Leaving Haskell behind

#350

Earlier quoted context omitted.

Does every usage site have to change? You would alter fibonacci to be: fibonacci :: (MonadLogger m, MonadState (Int, Int, Int) m) => m Int fibonacci ... and now of course all callers must support MonadLogger. But instead of using the MonadLogger (or any mtl constraint directly) you should just be constructing an abstraction boundary with a type class synonym: class (MonadLogger m, MonadState s m) => MyMonads s m and…

I have seen this in the wild. The result often is that every function has a kitchen sink MyMonads constraint of which it only uses a tiny subset. It's death by a thousand cuts. If you make such a class for every monad combination you get insanely large amount of classes. It's simply unworkable. Which is why you get the kitchen sink monad pattern.

If you think it's fine that you can log from all functions in other languages, then what's the problem with adding that constraint to all your Haskell functions to allow this?
Post reply on HN