Live data from Hacker News

Leaving Haskell behind

journal.infinitenegativeutility.com

381–390 of 402 posts

Re: Leaving Haskell behind

#381
post #247

Earlier quoted context omitted.

What is wrong with Java's tooling?

Maven is awfully slow and awfully stateful (plugins or multiple executions interfering with each other), has too many quirks, and documentation is lacking. Gradle is imperative and also stateful. Dependency injection and annotation-driven development is “magic happens here” that is hard to analyze when something doesn’t work, and hard to reason about in the sense of building a proof that it will always behave in the…

> Dependency injection and annotation-driven development is “magic happens here” that is hard to analyze when something doesn’t work

I don't quite get the criticism against annotations. Metaprogramming and code as data seem to get a lot of love in the context of lisp, python or ruby, but a lot of hate when it happens to be done in Java. I absolutely love the powers that reflection, annotations etc give me.

The difficulty of analyzing dependency injection and "magic happens here" is overstated. Just run the code in the debugger. And if you are having problems with the auto-configuration stuff, you can always selectively disable it and explicitly define the beans you need.

Re: Leaving Haskell behind

#382
post #302
post #64

I have been using Scala. I have found that it can give you the best of both worlds. You can reason algebraically, and often after a refactor, if it compiles, it works. Type inference and monads works great too. You also get to benefit from being in the java ecosystem. In instances where it gets too esoteric, I can break rules and code more like java. I am curious what others think.

I have really enjoyed Scala for the same reasons. Has some escape hatches if needed, and a large ecosystem. sbt drives me insane though, and is probably my least favorite part of the development experience.

I share the hateful sentiment. Too much magic and mystery in sbt for me

Re: Leaving Haskell behind

#383

Earlier quoted context omitted.

> The community went from Cabal (and the infamous Cabal hell) to Stack, and back to Cabal. I didn't know this. I've been away from Haskell for a couple of years. When I last used the language, Stack seemed like smoothest experience and solved many of the pain points with Cabal. The community went back to Cabal? What did I miss? :)

I currently don’t use Haskell but maintain an old Haskell package from a failed startup of mine that has some commercial usage by other orgs. I have been assuming everyone is using stack? I’m also interested to hear what is going on here

Just came here to say that I re-installed Haskell on a new ARM MacBook and the tooling is fine ... everything setup in about 10 mins and everything worked just fine.

Re: Leaving Haskell behind

#384
post #374

Earlier quoted context omitted.

Have you tried Rye? https://github.com/mitsuhiko/rye This is probably the best package manager I used for Python. It feels a lot like Cargo. It sticks to the standards of Python. No custom lock files ect. Uses prebuilt Python so you don't have to build it. Handles global installs easily.

> Correctly installed, rye will automatically pick up the right Python without manually activating the virtualenv. That is enabled by having ~/.rye/shims at higher priority in your PATH. I dislike this pattern. I don't want every language/tool manager in my PATH all the time. I much prefer the direnv. I hook only direnv into my shell. Then I can do what I need with an `.envrc` in each project directory.

I hate shell infection because 1) it only works in the shell, 2) it’s not stateless, and 3) depends on your working directory. I mean there’s a reason it’s called “shell infection”. Sounds like Rye specifically aims to address that issue. To each their own, I guess.

Re: Leaving Haskell behind

#385
post #125
post #71

Earlier quoted context omitted.

FWIW, the thing which really sucks about cargo is how it handles cross-compilation. Most "professional" workflows are always cross-compilation: even if you are technically on Linux already you don't want to build for the exact version you have so you create a sysroot and cross compile towards it... and cargo is somehow so bad at this that increasingly large numbers of projects are being forced to turn on a environmen…

You can set a default build target for a Cargo project with two lines of configuration, no nightly features necessary: https://doc.rust-lang.org/cargo/reference/config.html#buildt... Can you clarify what this is referring to? > the goal should be to make extremely difficult things easier to pull off, even if it means the simple things have to be a bit harder There are dozens of existing build systems that have this p…

> ...but at the end of the day Cargo is the reason that Rust is popular.

FWIW, maybe that's true for you, but there are numerous other advantages to the language for which many people choose to use Rust--some even "despite" Cargo: you see Google having had to put in way way WAY too much work to get Bazel working for Rust :/--that it honestly feels a bit like belittling an extremely important language to make this claim so flippantly.

In my case, I often feel bad that I'm not using Rust more often, as I'm one of those developer churning out tons of C/C++ code. I do my best, but... I'm a security engineer! I know what I'm doing is stupid! But like, I'm having a hard enough time just dealing with the Rust library dependencies I've accumulated, so I'm not going to start developing even more Rust :(.

> You can set a default build target for a Cargo project with two lines of configuration, no nightly features necessary...

This doesn't work as, as soon as you start setting target-specific options, it infects the host's options, as they incorrectly modelled the problem as some kind of map from targets to flags. If you don't believe me, on your Linux computer, try cross-compile something complicated that will runs on a "least common denominator" Linux distribution, such as CentOS 7.

> Can you clarify what this is referring to?

Sure. I've Googled rust cargo target host bugs for you (which, FWIW, finds a number of bugs I've filed or have talked about, but it isn't as if I have a list anywhere). Note that one of these bugs is "closed", but I still provide them for context as a patch might have been merged but (as you'll find out if you read through all of these) it isn't stable.

https://github.com/rust-lang/cargo/issues/8147

https://github.com/rust-lang/cargo/issues/3349

https://github.com/rust-lang/cargo/pull/9322

https://github.com/rust-lang/cargo/issues/9453

https://github.com/rust-lang/cargo/pull/9753

The result of this work being left incomplete is that increasingly large numbers of "serious" projects--things I'd expect people in packaging land to have heard of, such as BuildRoot--are being forced to set the ridiculous environment variable __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS="nightly" in order to get access to a flag that makes Cargo sort of work.

I remember a bunch of other ones but I think they are linked from these bugs (I didn't want to dig too long on this); you can also find--either linked from these bugs (as people will tag the bug in their patch) or by searching for that variable (as no one else would use that in a sane project) the projects that are slowly being forced into this crazy workaround.

(What is sad is I often see people surprised at how long it is taking for various of the more important clients to fully get into using Rust, as the safety issues are so severe from continuing to use C/C++; as you made the contention that you believe the reason why people use Rust is Cargo, I will say the opposite: the reason why we don't see more Rust is also Cargo.)

Re: Leaving Haskell behind

#386
post #263
post #71

Earlier quoted context omitted.

FWIW, the thing which really sucks about cargo is how it handles cross-compilation. Most "professional" workflows are always cross-compilation: even if you are technically on Linux already you don't want to build for the exact version you have so you create a sysroot and cross compile towards it... and cargo is somehow so bad at this that increasingly large numbers of projects are being forced to turn on a environmen…

Just do the build in a container modelling the appropriate environment. You don't need cooperation from the build tools (apart from controlling instruction selection), and you also don't need to trust that the build tool has implemented this feature correctly!

FWIW, it is easier to just not use Rust as the only serious build system I've had to work with that doesn't support this correctly is Cargo; and like, the mental model you are describing causes all kinds of other problems as it implies that if your build tooling simply can't run on a system old enough that you have to drop support for that system... people who are compiling serious apps (think Chrome or Ubuntu itself) and managing backports aren't sitting around with their CI systems running some old version of CentOS or Debian and praying their build tools continue to run on them: they just cross-compile.

And like, that Cargo doesn't handle this correctly is kind of silly as one of the engineers from BuildRoot seriously broke his back for a year jumping through hoops with them to come up with a compromise and satisfy all of their roadblocks (the Cargo people would rather spend hours talking with people about a patch than spend a few minutes touching it themselves... it was honestly demoralizing, but I've seen the same thing from projects like Flutter, so I think that it is just the reviewer / developer power dynamic that big tech taught a bunch of people) and the code is even in Cargo and yet is rotting in nightly.

(Meanwhile, I often see people bemoan how large projects aren't picking up Rust and using it to slowly cannibalize the C/C++ code in various projects, or are looking at distributions demanding answers for why there has been such struggle getting Rust code distributed, but the answers lie in the build model of the language and in no small part how difficult it is to use Cargo. If you just want to not care about those use cases and want to focus on self-compiled use cases--maybe you are doing web development!--that pick up all of the idiosyncrasies of the build system, then the community should just say that.)

Re: Leaving Haskell behind

#387
post #251

Earlier quoted context omitted.

But that can't be runtime dependencies to your code? I've written a couple of Maven plugins and you must declare your dependencies explicitely even for those. Pulling in stuff dynamically would be possible but not very clever.

The maven surefire plugin downloads dependencies dynamically depending on the kind of tests it finds. Is it not very clever? I agree. But it's one of the most popular maven plugins.

During Maven build, sure. But it does not add unknown dependencies to your code at runtime.

I am used to classpath problems with surefire but that it downloads undeclared stuff is new to me. Afair it pulls only in transitive dependencies. Could you give an example?

I am mainly building war files and it turned out to be good practice to explicitely declare any ambigous transitive dependencies. There's even a Maven plugin which shows up classes with different hash during build, https://basepom.github.io/dependency-versions-check-maven-pl...

Re: Leaving Haskell behind

#388
post #373

Earlier quoted context omitted.

> But code written from scratch doesn't have that issue. I'd be interested in a counterexample -- is there a code snippet that passes the strict mode of the compiler, and doesn't interoperate with untyped code, but produces an unexpected runtime error? You'd think so, right? But no, typescript is deliberately unsound in ways that have nothing to do with gradual typing. Here are a few examples. Signatures written in m…

Great examples, thanks!! I typed them all into the TypeScript playground. I agree this is weird, and seems to follow from TypeScript's heritage as "trying to describe whatever dynamic JS does" I mean that's probably why I didn't use it for >10 years (in addition to its JS heritage). But I did find that there is an interesting subset, at least for playing around. I think the JSON.parse() issue is fundamental -- it's n…

[deleted]

Re: Leaving Haskell behind

#389
post #373

Earlier quoted context omitted.

> But code written from scratch doesn't have that issue. I'd be interested in a counterexample -- is there a code snippet that passes the strict mode of the compiler, and doesn't interoperate with untyped code, but produces an unexpected runtime error? You'd think so, right? But no, typescript is deliberately unsound in ways that have nothing to do with gradual typing. Here are a few examples. Signatures written in m…

Great examples, thanks!! I typed them all into the TypeScript playground. I agree this is weird, and seems to follow from TypeScript's heritage as "trying to describe whatever dynamic JS does" I mean that's probably why I didn't use it for >10 years (in addition to its JS heritage). But I did find that there is an interesting subset, at least for playing around. I think the JSON.parse() issue is fundamental -- it's n…

> I think the JSON.parse() issue is fundamental -- it's not clear what they could have done better, and static languages don't really do better.

The best solution, IMO, is to give up on "no type-directed emit" (which harms the language in lots of other ways as well) and derive appropriate parsers at compile-time. Parsing malformed data should fail immediately, not just when you try to use the broken parts. This is a solved problem in C#, C++, Haskell, and no doubt many other languages.

Failing that, it should return an appropriate `JSON` type. Something along the lines of

    type Field = string | number | boolean | null | JSON
    type JSON = {[key in string]?: Field } | Field[]

Re: Leaving Haskell behind

#390

My notes on using Haskell: mostly agree with the article, but I came to embrace rolling my own tooling, some abstraction on top of cabal. I use my abstractions, not what whoever would force on me. Use Haskell as your typed lisp.. with all the pros and cons. On production use... Don't even get me started. Will work, but need shedding blood.

Typed lisp? Unlike Lisp, Haskell has enormously complex syntax, so generating code in it is a huge hassle. Template Haskell is something to use only when absolutely necessary, while Lispers write macros without a second thought. I considered your method of writing my own tooling, but have had a vague feeling that Lisp works better for this frame of mind.

Haskell has almost no syntax, even `$` is a userland function. Are you arguing against the feature of allowing ad-hoc infix operators in userland?
Post reply on HN