I'm excited to try out Dhall and see if it has a smoother onramp.
I'm excited to try out Dhall and see if it has a smoother onramp.
However - I now think that I understand Haskell's way of looking at numeric types and have not had this kind of problem for quite a while.
I will certainly agree that Rust's error messages are 1000x better, if you're looking for something similar.
After writing this comment I looked at TFA and I'd say read it and maybe even watch the author's talk on "why learning Haskell is hard". In spite of what I expected, the article addresses the ways in which Dhall is a good starting point. (Although readers should be aware that "Dhall is not Turing complete", which for most programmers is a bad thing.)
In my experience, people often describe their first experience with expressive static type systems in terms of "fighting with the compiler" (or similar phrasing). I think this is due to a poor introduction to static type systems, often in university settings.
A static type system has one purpose: to prevent you from running unsafe code. Every type error is just the compiler telling you "what you wrote isn't going to work". This isn't a fight; it's a conversation. You write some code, run the compiler, get back some errors, fix them, and run the compiler again. This process is repeated until your mental model of how the code should work is properly reflect in the code, as determined by the success of your compiler's type-checking.
There are frequently two sources of frustration in this process:
1. A difficult-to-use type system.
Some type systems are just obnoxious to use. (Older) Java required soooo much verbose typing. The resulting code would be difficult to read just because there was so much text on the screen. More modern Java is an improvement, but newer languages are often designed from the ground up to use type inference to alleviate your keyboard-typing obligation.
Another form of frustration is what you mention: inscrutable error messages. Haskell is pretty well known for having type errors that are not obvious to newcomers, and that turns the programmer-compiler conversation into a frustrating experience. Again, newer languages are making lots of progress here. I think Rust does a great job with its error messages, for example. Hopefully this is something the Haskell developers will look more into.
2. An insufficiently expressive type system.
If your type system is too limited, you'll have a hard time finding it particularly useful. If your types are "too big", they become unwieldy and unhelpful. Older languages frequently fared poorly in this metric, because "types" were meant primarily for memory optimization rather than programmer expressiveness. However, as our languages have become more user-centered, our type systems have become more expressive and, thus, easier to use to model data. Modern languages like Rust and Swift have taken a lot of inspiration from functional languages like Haskell and ML to provide type capabilities that are significantly more expressive than those in other languages.
I think type system inexpressiveness is a big part of why some people prefer dynamically typed languages, like Python. They find that they have a difficult time converting their mental model of the data into an explicit type, and so they move to an ecosystem where they simply don't have to deal with that. Personally, I think this indicates the need for better expressive type systems and better type system onboarding to teach people how to use them effectively, because if you rephrase the static type proposition to those programmers as "Would you like to guarantee that erroneous programs are simply never run?", I imagine most of them would enthusiastically shout "Yes!"
Maybe that was true 20 years ago, but most CS curricula offer mandatory (static) functional programming classes.
I did both my undergraduate and MS in the past decade, worked in academic research for a few years, and am currently in a PhD program. At the schools I've been at and schools I know well due to friends/collaborators, I think what I said still tends to be true for mandatory ("core") classes.
You are right, however, that students who choose to take an elective in a statically typed functional language are probably more likely to come away with a healthier relationship with their compilers, but this is only a portion of all students.
Maybe most top 10 programs do, but in general the variation in CS curricula is incredibly broad and includes tons of Java schools that only focus on imperative and OO paradigms with only passing mentions of functional programming in elective classes.
I really have no idea if the data to support the claim even exists. One would probably have to manually comb through CS curricula to check. My suspicion is that it would not hold up.
I'm not sure if this is just a fact of life about FP or Haskell, or if it's something that could be improved on.
Well that's part of the problem, is what I mean. If you look at it as a "fight", that's often how it will feel!
That said, as I also said, Haskell's error messages tend to be more frustrating and mysterious than they ought to be.
> I'm not sure if this is just a fact of life about FP or Haskell, or if it's something that could be improved on.
No matter the cause, it can certainly be improved. Programming languages have largely not focused on user-centered design. Fortunately, there are some recently formed workshops seeking to get the ball rolling in that area, so hopefully over the next couple of decades we will see some significant shifts in the ease of use of popular languages!
That said, I think if you had tried a different statically typed functional language (OCaml or Scala, for instance), you would not be quite as frustrated. But then Haskell has my favorite type system among common statically typed functional languages, so there's really no winning haha. Hopefully it will improve over time!
That's not true. Java or C++ force you to type out the types every time to
- place constrains inside your program (both the caller and the called side)
- be explicit about it (if anyone else wants to read your code later)
E.g x = 5, y = 6, x+y does work in many languages. (Untyped languages, or languages with type inference.)It is an unambiguous command, and many languages would just do what you say, instead of forcing you to write code in a particular way that has absolutely no use for you.
Being said, I absolutely love Haskell's function type notation ( f :: A->B f x = doSomeThing x ), its type inference, and how easy it is to alias types. I want this notation in every other languages please.
It isn't so unambiguous when you use x = 230 and y = 30 for example...
That's not true for C++, with the auto keyword, which was a God send and made the code a lot more readable.
Strongly static languages like the ML ones are like having auto on drugs. If you like auto in C++, you'll like these languages. If not, you won't.
It is unclear to me which part of my comment is "not true". Could you elaborate?
> E.g x = 5, y = 6, x+y does work in many languages. > [...] > It is an unambiguous command
It is absolutely not unambiguous; you only think it is because it happens to work the same way in most languages.