Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Functional programming won't succeed until the tooling problem is fixed. 'Tsoding' said it best: "developers are great at making tooling, but suck at making programming languages. Mathematicians are great at making programming languages, but suck at making tooling." This is why Rust is such a success story in my opinion: it is heavily influenced by FP, but developers are responsible for the tooling.

Anecdotally, the tooling is why I gave up on Ocaml (given Rust's ML roots, I was seriously interested) and Haskell. I seriously couldn't figure out the idiomatic Ocaml workflow/developer inner loop after more than a day of struggling. As for Haskell, I gave up maybe 20min in of waiting for deps to come down for a Dhall contribution I wanted to make.

Institutionally, it's a hard sell if you need to train the whole team to just compile a project, vs. `make` or `cargo build` or `npm install && npm build`.



I think tsoding has the wrong idea here. Most mathematicians are not working on GHC or Haskell standards or even using Haskell. Most are still doing mathematics on pen and paper. Many use packages like Sage or Wolfram alpha. Few are using interactive theorem provers like Lean.

Haskell is a poor language to be doing mathematics in.

I’d say the majority of people working GHC are software developers and CS researchers. They’re a friendly bunch.

What’s holding back tooling is that the developers of the de-facto compiler for Haskell are spread out amongst several organizations and there isn’t tens of millions of dollars funding their efforts. It’s mostly run by volunteers. And not the volume of “volunteers” you get on GCC or the like either.

That makes GHC and Haskell quite impressive in my books.

There are other factors of course but the tooling is improving bit by bit.

The whole “Haskell is for research” meme needs to go into the dustbin.


I think he counts academic computer scientists more as mathematicians than developers.


C++ and Java wouldn't be where they are without CS researchers, so I think the point still stands. These people aren't doing useless work. They're the ones making sure Concepts won't break the entire ecosystem and that have made the JVM the beast it is.

Grit and determination will get you far but like it or not there is a ton of work that requires knowledge of mathematics and theory that you can't avoid if you want to make good things.

What's kind of neat about Haskell is how closely researchers can work with users and collaborate on solutions.

Remember, the GHC team is pretty small. Their IRC channel isn't huge. Releases still get made fairly regularly and GHC is running one of the most advanced industrial strength programming languages out there with a large ecosystem.


> C++ and Java wouldn't be where they are without CS researchers, so I think the point still stands

I'm not sure how you gleamed that they aren't important/haven't made important contributions/aren't doing useful work from that comment. Tsoding specifically said that they don't make good tooling, but make great languages. It's not memeing about "Haskell for research," it's talking about things it needs to improve (potentially to break free of that meme).

For what it's worth, C++ tooling also sucks. We've just layered tons of kludges on top of it that make the ecosystem somewhat bearable. It's not ideal, contributing to a project for the first time usually requires some troubleshooting to get a working build.


> Tsoding specifically said that they don't make good tooling

And I disagree.

Mathematicians aren't building Haskell.

CS Researchers aren't noodling around either. I know a few of the people working on GHC who are researchers and are doing the hard work of improving error messages and reporting because they care deeply about tooling. They are also users after all!

> For what it's worth, C++ tooling also sucks.

Yeah, so does Haskell's. I think it's just an unfortunate fact of life that nothing's going to be perfect.

My point is that the reason for Haskell's situation is less to do with researchers and more to do with funding and organization.

To that effect, the Haskell Foundation is relatively new and gaining steam. It might change. But it's nowhere near the funding levels that get poured into TypeScript and C# or even Java, gcc, etc.

Update: Put it this way, the set of people building Python packaging is probably mostly developers and very few, if any, researchers. The tooling isn't great either. I don't think researchers make bad tooling and programmers make good tooling. I think programmers make stinking bad tooling all the darn time. Programming is hard. Tooling is hard. And programmers are a fickle bunch that are really hard to please.


He's talking about Programming Language Theory, which includes various type theories and such. It's where math and logic meet programming languages. In other words, the math of analyzing programing languages, not using programing languages to implement applied math.


A URL's domain on your profile seem to be expired and hosts some random stuff


You gave up using a programming language after a day? And Haskell after installing/building some dependencies for 20mins? Tbh, this sounds like you were not really trying. What kind of experience with a programming language do you expect to have after a mere day? Learning takes time. Anyone might spew some not idiomatic code within a day, but really becoming proficient usually takes longer.

Do you have any references for the "Rust is heavily influenced by FP" thing? To me it does not feel that much FP. I have (for now) given up writing FP like code in Rust. ML-influence -- Yeah maybe, if I squint a bit.


> What kind of experience with a programming language do you expect to have after a mere day? Learning takes time.

It does, which is why you need tooling to get out of the way and let you actually learn. Working out obscure tooling commands to build a hello world app then having to grok the error messages absolutely destroys the learning loop.

For rust it took me approximately 3 minutes from scratch to install, bootstrap a project and run the hello world CLI. The rest of the day was spent purely, 100% learning rust. Not Cargo.

20 minutes to install some beginner level dependencies, presumably with little feedback as to what is going in? Dead.


You shouldn't need to install any dependencies beyond `base` for hello world in Haskell:

```

module Main where

main :: IO ()

main = putStrLn "Hello, world!"

```

If you mean installing Dhall's dependencies (https://github.com/dhall-lang/dhall-haskell/blob/master/dhal...), those aren't too crazy, but they're definitely not all "beginner level". Template Haskell in particular is quite heavyweight.


As I see it, this is a completely legit beginner level perspective. When I first touched a programming language (C, Borland compiler) I was able to run a first program within minutes. I completely understand the frustration with development environments that frustrate an aspiring user unnecessarily - I had this experience with F#, VSCode an Ionide, which is a very ugly case. Haskell was not that bad, but it it certainly is not for the faint of heart.


> You gave up using a programming language after a day? And Haskell after installing/building some dependencies for 20mins...

I'd do the same. It's 2022. There are so many options without this friction, why would you fight your way through it?

If either language had some magic power or library, that'd be one thing, but their only selling point is the FP paradigm, which is only arguably somewhat better than what other languages do. Not only that, but most other languages let you do FP to varying degrees anyway.


Haskell's promise is not only FP. That's part of it though, of course, to have an ecosystem, which encourages to continue in an FP style. Haskell's promise is also strong type safety and, as a distinguisher to many langauges, lazyness by default. Aside from that, its implementation is quite performant, if one needs to worry about such things.

I will take a 20min build process for dependencies (probably a few commands, which hopefully are documented in the project's readme and probably only once for most of the lifetime of a project on your personal machine) over a language, that is quickly up and running, but breaks any number of basic principles (for example looking at JS) and lets me shoot myself in the foot. Some languages and the lessons we take from learning them are worth some initial effort. Of course it is not great, that things are not as easy, as they maybe could be, but if the language has other perks making up for that, it might still be worthwhile.


> but if the language has other perks making up for that, it might still be worthwhile.

Totally agree, I just think for the vast majority of developers, the trade off here isn't worthwhile. This is reflected in Haskell's stagnant growth despite it's model being better for a lot of things.


Sure -- people have the right not to try things, which is basically what messing around with a programming language in a new language paradigm for 1 day is. That's fine, although it should also be expected that their opinions on things they haven't tried won't be given much weight.


Day one experience matters a lot to most people. For better or worse, your community won't grow if newcomers have to spend a day hating things first.

It won't matter if you're looking for a language to make your baby for the next 5+ years, but most people are trying to solve small problems on an incremental basis.


> Do you have any references for the "Rust is heavily influenced by FP" thing? To me it does not feel that much FP.

The original implementation of Rust was in an ML dialect (I think OCaml?), so from that we know immediately that the original authors were familiar with FP and used it for their own purposes. It seems odd, then, to assume that there would be no influence of their own language.

But if we look at the actual feature set, we find a lot of things that previously belonged almost entirely to the realm of FP. The type system as a whole has a fairly FP feel, plus algebraic data types, exhaustive structural pattern matching, maps and folds, anonymous functions, the use of the unit value for side-effecting work, the functioning of the semicolon operator (which is identical to the OCaml usage)... there's quite a lot, and those were just the examples off the top of my head!


Yep, though it's got type-classes specifically from Haskell.


(It was OCaml, yes)


My job/hobby is to produce code. It is not fighting a toolchain. It does not bode well for long-term efficient use of my [limited] time if I'm spending a whole day fighting toolchains from the outset.

User experience matters, and developers are ultimately users.


IME learning the (usually shitty) tools and the culture/ecosystem eat up way more time when starting with a new language than learning the language itself does.

I can absolutely understand abandoning such an effort if one's earliest interactions with the tools and/or ecosystem are very unpleasant.


Immutability, most things are expressions, no nulls. I think this is what they mean, it's a good experience if you want to go purely functional, they took influences from everything though.


other things require my attention and there are so many hours in a day

either get those initial minutes right or lose me


I think FP suffers from what I call the "ideological gruel" problem. A lot of niche ideology-oriented communities with very strong opinions tend to ignore usability issues not necessarily because it's a theory/practice dichotomy, but that the highly ideologically excited community ignores the problems because they're so positively motivated by the ideology. So even if you're eating gruel, if the gruel is produced by an ideology you identify strongly with, the identification alone is enough to make the gruel taste better than mere gruel. A lot of folks that use FP are willing to overlook the myriad of rough edges around tooling because they're so excited to work with FP that they often get used to the tooling. Rust made tooling UX an explicit focus of the project which is why it was able to escape the "ideological gruel" curse.

Additionally most prominent FP projects are old. Both Haskell and Ocaml date from a time when UX expectations around language tooling were much lower (think C++.) The inertia around the projects never cared much for UX anyway so now in 2022 when languages like Rust and Go have raised the floor of expectation for PL tooling, Haskell and Ocaml struggle to keep up.


That's interesting, I often find the tooling one of the best things that FP languages offer. In OCaml for instance I found Dune to be fantastic and extremely intuitive. Another very good experience I had was with Elixir and Hex. In Haskell I personally think that there are indeed quite a few things that could be improved around build system and packaging, but overall it's not really that bad once you learn the quirks.


It would the OCaml community a great service if you wrote up a beginner's tutorial on working with Dune.


I felt the small section on dune here was enough for me.

https://ocaml.org/docs/up-and-running

Teaching anything beyond dune build or opam install feels out of place for a beginner tutorial.

However, there really should be more examples of “how to do X in dune”. It took me a bit to learn how to pin a git repo for local use and installation.


Tooling is why Go gets its foot in the door much quicker than other languages IMHO. A single binary with no dependencies that does pretty much everything.


Indeed. Also formatting decided at the language level (gofmt) and a standard library powerful enough to accomplish most business tasks, so you can avoid 3rd party dependencies entirely if you want, while still being productive.


I've seen go programs fail to start because they were dynamically linked to some .so file I happened to not have.


They mean the `go` binary, not Go programs in general.


Yeah ‘Fully static’ requires some extra linker flags.


As someone who likes both mathematics and programming, I find this comment and the article too divisive for divisiveness’ sake.

Programming is applied mathematics. An assignment is not 'sloppy' like the article posts, it is just another kind of operation that can be done.

A proof is very much like programming, except you are also the parser, the compiler, and the (comparatively slow) computer. Learning to write proofs helps immensely with learning how to program.

We should strive to make our proofs and programs easier to understand, no matter the paradigm.


I think F# has a good tooling story, since it's part of .NET and a first-class citizen in Visual Studio. It doesn't get as much love from Microsoft as C#, but it's still quite nice to use.


After learning a bunch of programming languages and their corresponding ecosystems (incl. Rust, Lisps, Scala), F# is still my favorite by a long shot. Its only serious shortcoming, imo, is the tooling.

Visual Studio is great, but if you're not on Windows, your only practical choices are VS Code + Ionide (I was a sponsor for a while; ultimately lost hope), or JetBrains Rider, which is powerful, but heavy.

Comparing my 10+ years focused on C# with ~5 years focused on F#, I was ultimately more productive in F#. But:

1. Tools for refactoring and code navigation were better for C# 2. Testing was more predictable with C#; I often just tested from the CLI with F# (so much love for Expecto, though) 3. Paket and dependency management between projects caused days of pain, especially during onboarding


Microsoft has come a long way in supporting .NET on non-Windows boxes, but I agree that it's still not as good as it could be.

C# certainly has better tooling, but C# has possibly the best tooling of any programming language on the planet, so that's a high bar to meet.


I used Visual Studio on macOS for some small F# projects and it worked fine. The only trouble I had was with some setup instructions being spotty because there was a shift in how things were done in recent versions at the time a few years back.


There’s also the jetbrain ide that I’ve heard good things about compared to ionide.


Yes, we ended up buying JetBrains Rider; I used it for a few years. I was much more productive in it than Ionide.

Code analysis was excellent, though it would sometimes get weird on multi-project repos. Unit testing (incl. Expecto tests) were a little flaky. Like many JetBrains products, it was a resource hog on large projects.

Probably the worst part of the Rider experience had more to do with other devs using different tools, i.e. Ionide or Visual Studio. (We were a "bring your own whatever" kind of startup.) Each IDE/toolchain had its own opinions about .fsproj files. A CI step to keep things "normal" would have been great, but there wasn't (isn't?) anything available, and we wouldn't spend the time building our own.

tl;dr - Rider better than Ionide; whole team should use it


Last time I used F# on Linux, the REPL was a mess and mostly unusable. Compilation takes forever. You have to edit an fsproj rather than inferring modules from the file system structure like most modern languages.

It’s a great language— maybe my favorite, but the tooling stinks if you’re not using VS. I’m not switching to Windows, so that leaves me in limbo.


PSA: Visual Studio for Mac[0]. I know you're on Linux but for others.

[0] https://visualstudio.microsoft.com/vs/mac


And just for clarity, it's not proper Visual Studio, but rather an updated MonoDevelop. Was missing quite a lot of functionality (for Unity/C#) compared to VS, so I used Rider instead.


I didn't know Rider supported F#, thanks for the tip.


I'd argue Rider from Jetbrains is better than VS for F#, though that is a subscription based IDE (though you can stop paying and keep the version you originally "bought" after)


The part about fsproj is due to module order being significant, which I don't think they can change without breaking existing code.


Honestly Haskell's tooling is really surprisingly good these days. It works fine cross platform, there is a single "blessed" path without too many options to spend time agonizing over.

Today the Haskell example is just `cabal install --only-dependencies && cabal build`.


The npm install experience should be baseline for newer languages. Simply let me get into hacking fast. This is one of the top reason I like tinkering with JS because it just works. (Yes, I know all weaknesses of JS ecosystem, but getting is really easy)


Please, no. Node tooling is such a mess and I can almost never get anything running easily on Nix because Node developers download binaries from the internet without understanding the system. All of these executables fail because of linked libraries. If instead they told you what libraries and executables you'd need instead loosy-goosy installing garbage all over my system, more things might work.


Sure npm is not silver bullet. But I want the npm experience. Technical implementation can be improved as you say and I agree.


Then you should be a fan of Nix


I do agree.

I think .Net has got it right. And dotnet-script [https://github.com/dotnet-script/dotnet-script] has been a game-changer for me with a REPL-like experience for unit testing and writing command-line utilities.


Not only tooling is a problem. Name one FP language that I can use for high-performance and systems programming. Is there any one except ATS?

And ATS is pretty hard (unlike C, C++ and Rust). I think it will take a while until linear & dependent type languages will hit mainstream. Rust already succeeded in that regard, so it's a great stepping stone.


Most computers follows the Von Neumann architecture. Any imperative languages with no GC would do great because of the small number of abstractions needed to make a program run. AFAIK, C only requires to set up a stack with the registers.

When we build something with lambda calculus as its core, you might want to revise that opinion.


There’s some truth to this - imperative languages with state make sense because the underlying hardware is a series of imperative instructions and a large amount of state. What does lambda calculus hardware look like?



> it is heavily influenced by FP

Is it really? I agree with the rest of your post, that Rust provides great tooling, but not sure it's "heavily influenced by FP", at least that's not obvious even though I've been mainly writing Rust for the last year or so (together with Clojure).

I mean, go through the "book" again (https://doc.rust-lang.org/book/) and tell me those samples would give you the idea that Rust is a functional language. Even the first "real" example have you mutating a String. Referential transparency would be one of the main point of functional programming in my opinion, and Rust lacks that in most places.


Considering Rust pretty much started as a way to have a ML for system programming and was written in Ocaml, yes, I think it's fair to say it was heavily influenced by FP.

It became less and less ML-like as time went on but it still as a ton of features it inherited from Ocaml and Haskell: variant types, pattern matching, modules, traits come directly from type classes, etc.


I think Rust is not particularly FP because it encourages using loops instead of recursion and “let mut” is quite idiomatic in my understanding. Those two characteristics are more relevant than the type system. For example, Scheme and Clojure don’t have type classes but are clearly FP because recursion and immutability are idiomatic.

In Rust, even though it is true that .map, .fold, .filter, and .zip exist, first of all they also exist in Python, and second, they need to be sandwiched between .iter and .collect unless one is working with iterators which makes the code noisier and pushes the needle toward loops.

The influence of OCaml and Haskell is clear though, and it makes the language more pleasant to use.


The claim was that Rust is "heavily influenced by FP"; I think that's clearly the case, while "Rust is FP" is probably not (which case you make pretty well).


FPLs yes, FP no.

We might argue it's influenced by FP indirectly because those adopted features from ML etc also jive well with functional programming, for example pattern matching as a control flow construct...


Eh, I think that's a distinction we could make, but it's not clear to me it's useful, and FPLs themselves are (definitionally?) shaped by FP.


It's true it's arguable. But if we start calling the languages that adopt FPL pioneered features "heavily influenced by FP" we end up putting a lot of languages in that set, like Java, Python etc for having GC and closures. So in order to use that as a distinguishing feature I think it's warranted to make the distinction.


I would phrase this as: adopted PL features pioneered by FP languages, but not in support of functional programming.

Like Java.

I think we come upon a phenomenan of cultural treatment of FP that makes it like AI - over time time some of the stuff invented initially invented and used in FP languages becomes adopted in mainstream languages (like eg closures, garbage collection, etc) and it gets gradually detached from the FP languages association and mainstream programmers aren't even aware of the FP origins.

(The AI analogy being: particular approaches start out being called AI and if it works out, ends up being called just normal programming technique when its adopted in mainstream - https://en.wikipedia.org/wiki/AI_effect).


It's not a FP language, but it's clearly heavily influenced by FP.

Mutability is a significant part of Rust, but it's much more sharply curtailed than any non-FP language I've ever seen. To be allowed to mutate something, you have to prove that nothing else holds a reference to it. That means that any code that doesn't use mutability itself can pretend that mutability doesn't exist.


The entire "idea" of Rust is the ability to achieve memory safety by mutation XOR multiple references, which is a different way to achieve the benefits of referential transparency/immutable data structures without the loss of performance.

Rust is not a "functional language" in that sense, but that was not the claim made, which is that Rust is heavily influenced by FP. This is most clearly seen in the trait system (typeclasses) and iterator patterns.

Influence doesn't mean you're doing exactly the same thing. If I make a rock band influenced by classical music, that doesn't mean I'm doing classical music, but I'm still very obviously influenced by it.


Most (all?) dependency management systems are single threaded and download thousands of tiny files one… at… a… time…

I have gigabit internet and I’m lucky if some package manager can get more than a couple of megabits of throughput.

Most industries would never accept less than 0.5% efficiency, but apparently software developers’ time is just too expensive to ever be “wasted” on frivolous tasks like optimisation.

I kid, I kid. The real problem is that the guy developing the package manager tool has the package host server right next to him. Either the same building or even a dev instance on his own laptop. Zero latency magically makes even crappy serial code run acceptably well.

“I can’t reproduce this issue. Ticket closed, won’t fix.”


I'm really happy with Meson, as a lot of Wayland (the new display protocol for Linux, the "successor" of X11) apps seem to be built in C, so using meson is super simple and I don't have to worry about tooling (I don't deal much with C/C++, so let me make my change and run away please).

Rust is the same, you can even define a nightly version if you want, so even the correct version is ran with rustup. It's fantastic, and I can contribute much easier to projects without worrying about tooling.


> I don't deal much with C/C++

that is because there is no such thing.


the slash symbol is often used to denote multiple entities. For example, "I don't deal with foo / bar" usually means that the commenter doesn't deal with either foo or bar. The commenter is not claiming that foo and bar together constitute a single entity.


C/C++ is just 1 in the limit, right?


two things wrong with your statement:

- the ++ operator only acts on integer types, not floats or doubles, so there is no limit to speak of here

- the expression "C++" has value equal to C before incrementing, hence the expression "C/C++" is just one for positive C, even when C is small


Hey, wait a minute, ++ is defined for floats.

It might be a bad idea to use it in many cases (since there are values for which the result is just rounded back to the original value), but it works!


So, luckily my mistakes cancel out -- C/C++ = 1 always, so it must also in the limit. Once we figure out how to define limit.


> the ++ operator only acts on integer types

no, I believe it works on pointer types and enums as well


It is also defined for floats.

Using it seems like a bad move though -- for large values it can round back to the input value.

Indeed, the following stupid test program works, although it may heat up your laptop slightly.

    #include <stdio.h>

    void main()
    {
      float C   = 1.0f;
      float Cin = 0.0f;
      int i=0;

      while (Cin != C)
      {
        i++;
        Cin = C;
        C++;
      }
      printf("%i %e\n", i, C/C++);
    }
And, it finally lets us confirm what the mathematicians never could. When does the limit happen? 16777216. No further questions.


The only problem I had with tooling using F# was getting my dev env set up. The only help I need from the editor was navigating between classes/functions and build/run.

Even refactoring was easier because the types are sometimes left to be inferred and not named everywhere. The type inference in F# being weaker also even helps with both compile speed and readability where annotations are needed both to help the compiler and the reader.

Perhaps on larger projects other things become important, but I got the sense that it's on the devs to name things well, use type annotations where helpful, and otherwise document non-obvious aspects.


There are plenty of non-academic languages with tooling issues as well. I think the larger issue is simply if the language has significant usage in a large corporation who can sponsor tooling development, or not.

Most tooling issues are pretty minor for small apps, it’s once one employs scores of developers that the lack of tooling begins to hurt (and by hurt, I mean cost money).


> I seriously couldn't figure out the idiomatic Ocaml workflow/developer inner loop after more than a day of struggling.

I tend to agree but, compiling C++ isn't just about typing "make". And it did take me more than one day to figure out python/js workflow.


> Functional programming won't succeed until the tooling problem is fixed.

I think different people have different wants and needs with tooling. I make (and use) binaries with Haskell. I wish more mainstream languages could make binaries.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: