Live data from Hacker News

Leaving Haskell behind

journal.infinitenegativeutility.com

331–340 of 402 posts

Re: Leaving Haskell behind

#331

Earlier quoted context omitted.

I don't have any issues with Python's packaging ecosystem anymore, having settled comfortably into a pyenv+virtualenv+pip-tools as my "stack" after going around the block a few times. But even so, I must recognise how awful the experience is for new users. It's taken me years to settle into this system, and it can take half a day to get someone up to speed with these tools if they haven't used them. I also work a lot…

I have issues precisely because of the misguided preference for virtualenvs in favor of traditional system package installation. It's obnoxious that pip now admonishes you for installing into site-packages even on a Debian system where that can't cause massive breakage. When you need isolated containers it's great. Everyone doesn't need a webdev focused, reproducible build for everyday shell life.

In my personal experience, it's absolutely necessary. Breaking changes are all over the place. I have non-dev coworkers who have built Python tools without any knowledge of package management, and it's a minefield getting it up and running.

For individualised shell usage, sure. I have global installations of common data science utilities like pandas and jupyter, or requests.

Reproducibility isn't just about deployment, it's also about coordination with colleagues.

Re: Leaving Haskell behind

#332
post #255

Earlier quoted context omitted.

As someone new to using Python professionally after having used it here and there over the course of 15+ years, I’ve run into exactly this problem. It’s pretty standard for a language these days to bundle the dependency manager and build tooling. Python still does this via shell infection. And since there’s 5 different ways to do it it can leave someone trying to figure out what the right vibe is in 2023 spending hou…

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.

This is very interesting indeed! A lot of the design choices fix issues I've also personally encountered. The "experimental" dissuades me from using it for real projects, but I'll be keeping an eye on it.

Re: Leaving Haskell behind

#333
post #87
post #84

> The way that Haskell-the-language evolves — well, the way that GHC evolves, which is de facto Haskell since it's the only reasonable public implementation — is that it gradually moves to correct its past missteps and inconsistencies even in pretty fundamental parts of the language or standard libraries. I would say that the biggest problem is that GHC is tied to a particular version of base (the standard library).…

> I still don't understand why this is necessary. Why must code compiled with GHC 9.6 use base version 4.18.0.0? It's hinted at in the section you quoted. A newer ghc might reject older base code as invalid.

That GHC might reject an older version of base isn't a reason to switch for every GHC release, is it?

I mean, if it breaks then sure, require a newer base. But in my experience GHC (thankfully!) doesn't change the semantics of Haskell often enough to warrant a new version of base for every new GHC version.

Re: Leaving Haskell behind

#334
post #256
post #84

> The way that Haskell-the-language evolves — well, the way that GHC evolves, which is de facto Haskell since it's the only reasonable public implementation — is that it gradually moves to correct its past missteps and inconsistencies even in pretty fundamental parts of the language or standard libraries. I would say that the biggest problem is that GHC is tied to a particular version of base (the standard library).…

> 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.

Re: Leaving Haskell behind

#335

In terms of tooling, Haskell has one thing that AFAIK no other language can compete with: Hoogle. Hoogle is amazing. You tell it, in Haskell, what you want, and it tells you, in Haskell, what you can do. It's extraordinary. Someone attempted something similar with Rust, and I even tried to make a Noogle (Nim), but it just doesn't work the same in languages where there's a clear divide between "passing arguments to a…

Hard agree on Hoogle — it's amazingly useful.

But wrt. other tooling, I use haskell-language-server every day and it makes me so much more productive. Sure, it isn't perfect, but so much better than what we had just five years ago.

Re: Leaving Haskell behind

#336
post #325

Earlier quoted context omitted.

> AFAIK TypeScript's type system can do everything in OCaml -- it's extremely expressive Extremely expressive and unsound . And not just in a trivial "escape hatches exist but you should never use them" way - until you've been burned enough it's not at all obvious which operations are unsafe, and there are a lot of them.

I think if you're writing code from scratch, this doesn't really apply -- I'm talking about prototyping language implementations without any libraries at all, sorta like you would do with OCaml from a textbook (e.g. TAPL by Pierce) (I'm aware of all the terrible experiences people have with TypeScript in the NPM ecosystem. But TypeScript is a big, mature tool and you can use it in more than 1 way.) I just noticed the…

> 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 method syntax are bivariant, which is not correct

    interface Unsound {
      f(x: number | string): number
    }
    interface Unsound2 {
      f(x: number): number
    }
    const a: Unsound2 = { f: (x: number) => x }
    const b: Unsound = a
    const c: number = b.f("not a number")
Type predicate results survive mutation

    const hasA = (x: object): x is { a: unknown } => "a" in x
    const deleteA = (x: { a: unknown }) => {
      delete x.a
    }
    const unsound = (x: object) => {
      if (hasA(x)) {
        deleteA(x)
        return x.a
      } else {
        return "no a"
      }
    }
Many stdlib types are incorrect. JSON stuff is particularly bad: JSON.parse and Body.json() both return `any`.

You can spread things that aren't objects

    const unsound = (x: X, y: Y): X & Y => ({...x, ...y})
    const bad: never = unsound(5, 4)
(And even for objects, `X & Y` is not the correct type when you have overlapping keys)

Anything with optional fields can be widened incorrectly

    const unsound = (t: T): { x: number, y?: number } => t
    const bad: number | undefined = unsound({ x: 5, y: "not a number" }).y
Assignment doesn't handle `readonly` properly

    interface Readonly {
        readonly x: number
    }
    interface Mutable {
      x: number
    }
    const a: Readonly = Object.freeze({x: 5 })
    const b: Mutable = a
    b.x = 4

> The OPERATION is legal, but the data isn't, which isn't something that any type system will tell you.

There are some that will, though unfortunately none that are really production-ready yet.

Re: Leaving Haskell behind

#337
post #88

Earlier quoted context omitted.

Fair enough, though I’ll note that only I’ve given an up-to-date reference.

In that same thread that you've linked, other people have later replied arguing for why they prefer Stack so... I don't really think that you've given an argument that is persuasive enough to someone who is new to Haskell. (And I'm not even that new to Haskell. It's just that I don't use it every day and when I come back to it and have to remember the weird incantations and dances I have to perform to make HLS not cr…

> In that same thread that you've linked, other people have later replied arguing for why they prefer Stack so...

I merely stated that I have no trouble running old projects using stack.

> I don't really think that you've given an argument that is persuasive enough to someone who is new to Haskell.

Honestly, cabal improved a lot since the old ages. For a beginner, either stack or cabal should be very fine imo.

> or want to overwrite my stack-installed Haskell version, I'm usually rather annoyed.

Not sure why you would want to do that. Either you use stack and let it handle your ghc install, or you don't, and I really don't see why you would use stack only for compiler install.

Re: Leaving Haskell behind

#338

In terms of tooling, Haskell has one thing that AFAIK no other language can compete with: Hoogle. Hoogle is amazing. You tell it, in Haskell, what you want, and it tells you, in Haskell, what you can do. It's extraordinary. Someone attempted something similar with Rust, and I even tried to make a Noogle (Nim), but it just doesn't work the same in languages where there's a clear divide between "passing arguments to a…

Hoogle is really amazing!

Inspired by it, I implemented something similar for FunctionalPlus (a functional-programming library for C++): https://www.editgym.com/fplus-api-search/

I'd love to see more projects taking this path too. :)

Re: Leaving Haskell behind

#339
post #164
post #20

As someone that has also written haskell for about a decade and moved away from it as a breadwinner recently (but for other reasons - I simply wanted to filter job offerings based on social utility rather than language stacks), I definitely agree with the author's first point: the Haskell community values learning extremely strongly. That's great because you work with curious people that have always something to teac…

> filter job offerings based on social utility rather than language stacks Any pointers on how to do this? A person that close to me is thinking about entering the High Frequency Trading world, and I would like to give them some alternatives.

Well, for starters you have to fight the urge to get as much compensation as you can. Once you realize that 90% of SWE job offerings will land you in the top 10-20% of earners, and provided you're fine with the lifestyle that allows, most companies need tech.

The two criteria I'm interested in as an IC is how useful the job is in my eyes (this you can know before applying), and whether the company gives me enough independence to be able to make things right. So my interviews focus on a single factor: whether the company culture and organization is conductive to good, productive work I will be proud of down the line.

Re: Leaving Haskell behind

#340
post #24

Earlier quoted context omitted.

> Take Java, for instance. It has added features like Streams, functions, lambdas, algebraic data types, records, and pattern matching. In a doomed attempt to escape the prison in which they were locked, the inmates defiled their language and adopted grotesque rituals inspired by the light they saw through the bars of narrow windows. They created an endless pit of suffering of their own, which is made tolerable only…

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 often at odds with each other. Best example is exceptions (esp. checked exceptions) and all Stream operations. They take a lambda which does NOT throw any exceptions. So, you need to either never use checked exceptions (which is impossible, because most libraries still do) or not use streaming, or create a horrendous hybrid.

Post reply on HN