197 karma · joined December 4, 2017
Conversely, in the case where something like a list is modified in entirety (e.g. with a `map` function), if the compiler can determine that the original is no longer needed, it can run the map operation in place - much like you might do on an array in C - avoiding the need for a second copy of the structure in-memory.
Most Haskellers I know are quite fond of Rust :)
That said, the type system _does_ stand in the way of learning it - though it's very powerful once you get your head around it - and lazy evaluation means you do spend more time than you'd generally like hunting down space leaks if you're writing the sort of code that's capable of getting space leaks.
(And to be clear: I use Haskell professionally and love it - but the syntax is _not_ why most people use Haskell).
In practice this is not actually a problem. It just takes a little getting used to to get yourself out of the 'memory-address as identity' mindset that procedural languages have.
This may let them capture a large chunk of the ML market from Python - and hopefully greatly improve ML apis while they're at it.
It's definitely not as nice as something like Visual Studio or IntelliJ, but it's not too bad.
This is also true for Haskell. It's not especially hard to get and use mutable variables, they're just not something that most tutorials cover.
Haskell _allows_ you to write some true type monstrosities (cf. Lens), but almost all the useful instances of that are wrapped in libraries. Types in app code are typically very readable and expressive.
My main complaint with Haskell's type system vs Java's is actually that Haskell has too few type annotations. The inference is good enough that you usually don't need anything besides the function header, which can make it harder to read code without an IDE if you don't know what types certain functions have.
The end result is _usually_ better (e.g. Lenses are in almost all cases an improvement over getters and setters; Functors, Monads and Traversable are an improvement over imperative control flow), but damn it it doesn't take a while to get your head around those concepts.
Consider a function "decode :: Read a => String -> a". What this returns (and what it does) is dependent on the type that the caller expects.
> <T extends Comparable<T>> T f(T a1, T a2)
Java may have improved this somewhat since I last used it, but the general complaint from Haskellers on this is how difficult it is to say that types must be equal. Consider the fact that java `.equals` is implemented in terms of `Object`, so there's no requirement that the argument be of the same type (or even of a comparable type) to the originating object. Contrast to Haskell's `==`, which can only be called with the same type on both sides. (There is no concept of referential equality in Haskell, so no equivalent to Java's `==`).
Also, I think you'd struggle with that extends trick once you started getting more complicated constraints. e.g, try something like: "T is traversable, A is orderable and serializable to JSON, and T<A> is a monoid".
> Higher kinded types
This probably gives a better explanation than I can be bothered writing: https://stackoverflow.com/questions/35951818/why-can-the-mon...
The TLDR is that there are some concepts involving higher-kinded types (such as Monads) which are simply inexpressible in Java's type system.
Stuff like "toString", "equals" and inequalities that you'd usually implement manually in something like Java are done for you automatically by the compiler, with a one-line directive.
That system is extensible as well, so for example you can automatically get Serde code for stuff like JSON, Avro, Protobuf etc with a one-liner.
On a more abstract level, there's a lot of stuff you can express in Haskell that's difficult or impossible on a technical level in Java. For example:
- Functions which are polymorphic in their return type, so that what they do is determined by what type the caller wants them to return.
- Function constraints - for example try to express "A function which takes two polymorphic arguments, which must both be of the same type, and which must be orderable (i.e have <, ==, >, etc defined for them), and returns the same type" in Java. In Haskell, that's just "f :: Ord a => a -> a -> a".
- Higher kinded types. These let you have (loosely speaking) polymorphic containers. For example, instead of List<A> and Set<A>, in Haskell you'd have something like Traversable t => t a, where Traversable is a particular interface you want your "container" to implement.
The community is one of the more helpful and responsive ones I've come across. You can generally jump on IRC and find either the people who wrote the stuff that's tripping you up (e.g. Ed Kmett for Lens and MTL), or people who know that stuff backwards and are quite happy to help (e.g. Tony Morris).
There are high quality libraries for _most_ common problems. A lot of them are vast improvements over what you'll find in other languages (e.g. Aeson for JSON serde & manipulation). Stuff like Amazonka often runs ahead of Amazon's official libraries, because it compiles directly from their API spec.
Are you going to run across holes? Sure. My team maintains a bunch of open-source libs for where we've found them. If you just want to do connect-A-to-B programming, Haskell is not for you - occasionally you're going to have to go and implement something yourself.
Above that, employee entitlements get paid out first in the event of bankruptcy/wind-up (i.e. before any investors or creditors see a cent).
Also, any director of a company that doesn't comply (i.e. keep enough cash on hand) is likely to 1) get banned from being a director of a company, 2) prosecuted, and worst of all 3) get reamed by the tax-office for the amount owing.
Healthcare is almost entirely public here. Employer-provided private health insurance is rare.