Hacker News new | past | comments | ask | show | jobs | submit login
Introducing Haskell to a Company (alasconnect.github.io)
130 points by k0t0n0 on Oct 2, 2018 | hide | past | favorite | 109 comments



I like haskell. It reads like a math proof more than a cooking recipe. very elegant. I'm a math guy and i'd love to get back to it in my free time.

But i don't think i could recommend it for the enterprise. not honestly. I tried to do a professional project in Haskell once. it was a good fit, since it was about parsing and generating configuration. However I was still new to it. the bottom line: it's just not that great for newbies. since most people are going to be newbies at it, i could not recommend it at all. sometimes i think the language even goes over my head, and I'm supposed to be a pretty smart cookie.

OP makes 'they are not going to be productive for months' sound like an obstacle to overcome. But if I tell management the honest story in advance and they will obviously not give me the greenlight.

But i suppose it is a language that's a reasonably easy sell to management if you hype up the reliability stemming from the type system and skip over the downsides. managers dont know much about programming, but they hate incidents even more than developers. if you are honest, you have to tell them that in practise operational problems become more likely. I mean: ever tried to install ghc on a centos server behind a firewall?

If i have to recommend something now it would be python. because it's easy and because i started using it for my personal stuff. i know lots of languages and that's what i end up coming back to if i need to do stuff quickly.

OP doesn't even mention the real advantage to introducing Haskell. Few colleagues will end up being good at this, so if a piece of critical software is written in Haskell and you are the only one who is a great Haskell engineer, it increases your negotiating power in the company. people won't be able to get around you and it will be hard to deny a request for increased compensation.


> the bottom line: it's just not that great for newbies. since most people are going to be newbies at it, i could not recommend it at all.

I don't think that disqualifies it for enterprise. People will start as newbies and they'll have a very difficult initial hump to get over but once they've been using it for a few months they'll be productive and after a few years they'll be very productive. Unless turnover is so bad that a substantial portion of your workforce is always "new", use of Haskell should be a net positive for a company.

There was a study a while ago (http://www.cs.yale.edu/publications/techreports/tr1049.pdf) that had programmers experienced in each language solve a simplified but non-trivial problem for the US Navy in their given language. Haskell was rated quite highly. There was even a case where a newly-hired college graduate was given 8 days to learn Haskell, with assistance from an experienced Haskell programmer. The college graduate was then asked to solve the problem using Haskell and still performed very well.

So I don't think it's impossible to learn Haskell quickly either, it just requires access to an experienced mentor, something an enterprise could provide.


I vaguely recall reading a story about this report — the Haskell solution was considered quite elegant, but some people felt that it was somehow "cheating" and not a real, fully-baked, solution because of the way it used functions to encode regions.


I also think we should stop linking the Navy study


> OP doesn't even mention the real advantage to introducing Haskell.

Yes, he does - contrary to the non-technical political motives you outlined - he outlines the importance of a strong type system for maintenance and refactoring—A property much harder to achieve in something like python.

I think your own experience of having some difficulty bringing your previous skills to bear on the language is not so uncommon—This is why mentors are so important.


I knew this discussion would end up discussing the type systems. That is really quite removed from business goals with very weak evidence that it will provide any real benefits to the business. It’s quite debatable even from an engineering perspective if the real world rather than theoretical benefits.


> he outlines the importance of a strong type system for maintenance and refactoring—A property much harder to achieve in something like python.

Of course a typed language is going to have a better type system than an untyped language... When you compare to a language like Java, your argument doesn't shine.


Haskell's type system is _worlds_ better than Java's, and it's absolutely essential to the maintenance benefits that Haskell gives you over other languages.


Just curious, but care to give a practical example of how it's worlds better?


Practically speaking, Haskell's type system gives you a lot of code for free.

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.


You need some better examples (your examples all appear expressible in Java):

> - Functions which are polymorphic in their return type, so that what they do is determined by what type the caller wants them to return

You'll have to be more specific here - polymophism in the return type is clearly trivial w/o specific constraints, e.g. <T> T identity(T x) { return x; }

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

<T extends Comparable<T>> T f(T a1, T a2)

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

Iterable<T>

If you're arguing that the Java version requires the types to declare that they implement Iterable, Comparable, etc, I think that's more a philosophical distinction about programmer responsibilities rather than a technical type system difference.

Haskell does have a fancier type system than Java, so you can actually present some interesting differences. However, my belief and observation is that for many smart programmers, Java's type system is already "too fancy", i.e., too hard for many people to use effectively. So I'm somewhat skeptical of the extra value brought by Haskell's type system.


I think one distinction is that typeclasses let you add some new 'interface' like Fooable and then implement them for standard types like String and Int as well as allow the user of the library to implement a version as well. With generic programming like Shapeless in Scala one could also recursively derive a Json decoder based on having Decode defined for all the components types of some nested arbitrary data object.

A lot of this stuff is possible in other languages for varying definitions of 'possible' which usually comes down to how much code you have to write to do this, how flexible it is with code you haven't explicitly written (i.e. standard prelude types or what have you) and how much the ecosystems that exist in these languages are oriented in a manner which takes advantage of these features.

Consider nullability in Java and how pervasive it is. Java has tons of great software but the type system is lacking based on how many functions could return null but don't document it, could throw an exception but don't document it, etc... This is predominantly because actually handling nullability on the type level, or error handling on the type level is not straightforward in Java.


> You'll have to be more specific here - polymophism in the return type is clearly trivial w/o specific constraints, e.g. <T> T identity(T x) { return x; }

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.


Sum types, not having null in every type, multiple dispatch (useful for numbers) and higher-kinded polymorphism (e.g. X can also be a type parameter in X[T]) are at least four very useful features that Haskell has and Java doesn't. Haskell also has excellent type inference that makes it as succinct as Python despite the static types.

In practice, despite the features Java can support, it's typically too much work to define a new type for safety reasons. Strings are used everywhere, instead of more domain specific types. Even the designers made compareTo return an Int!


So much this. I'm not actually that much of a fan of Haskell (might be due to a bad introduction to it), but dabbling in F#, I'm constantly amazed by how much more robust (and self-describing) you can design your APIs while still being way more concise than when using Java or C#.

Since Haskell's type system is still more powerful than what is achievable with the .NET CLR, I'd assume this effect to be even stronger there.

It's really amazing how far sane language defaults can get you. In C#, I encounter badly designed types all the time. The main reason for this is not that it is impossible to design them right, but that the language makes it so tedious. I'm also really longing for the new features in C# 8, in the hope that they manage to remedy some of that (record types, pattern matching and non-nullable references sound like a good start).


As a c# person, Sadly the pattern matching will not do exhaustiveness checking which makes adding new data to cases much more error prone than without it, so there is less incentive to move away from inheritance


I suspect there is a point of diminishing returns with this though; the extra complexity in the type system gets you less and less benefit but at a greater cost to code complexity/comprehension. It could explain why the mixed Scala/F# paradigm has more industry usage than Haskell right now. i.e. I am trading a type system that has a little more expressiveness for a large amount of libraries, ecosystem, rock-solid VM, testing, corporate buy-in, etc. In a .NET shop for example its much easier to just drop an F# DLL into your codebase (in VS create a new F# project in a few clicks); there's no need to change anything else (e.g. build machines, build tooling, testing tools) since it's all IL anyway; same goes with Scala and Java.

My experience in coding functionally has shown that mutation (especially if localized and doesn't leak outside of a function) can really help functional code become a lot faster. From what you describe C# is slowly becoming an F# clone; which may be a good thing or not. Still think that if you need these features you should move to Scala/F#/Ocaml/Haskell though since I suspect these features will be added to C# in a clumsy/compromise way given its roots (e.g Scala and F# already have exhaustive pattern matching, async streams/iterators, better type inference, etc.).


> mutation (especially if localized and doesn't leak outside of a function) can really help functional code become a lot faster

There's this magical thing in Haskell called the "ST Monad", where you can have a pure function (does not have IO in its type signature, does not use unsafePerformIO) that takes a normal value, returns another value, but can use mutation inside the function, and the type system guarantees that the mutation doesn't "leave" the function. So for those cases where, in C++ I would think "this function is pure enough, it doesn't print or order fish food, though it does mutate this temporary array", Haskell's compiler will actually confirm for you "yeah, you're right, it is pure enough".


> Still think that if you need these features you should move to Scala/F#/Ocaml/Haskell though since I suspect these features will be added to C# in a clumsy/compromise way given its roots

100% agreed, with one caveat: You usually don't get to go "Boss, we're using F# now, 'kay?"

Some workplaces are sadly very constricted in those terms. Maybe I'll see the day when my team gets to use a more functional language, but until then, I'll take what I can get.


Type system can prevent classes of mistakes.

One such example in my experience is modeling (and designing) hardware. Strict checking of lengths of bit vectors (just bit vectors!) will make mistakes like "incorrect interpretation of memory address" much harder to be made. Add another one: the "ready" bit for some bus values can be described as Maybe type. Pattern matching on value of Maybe type makes impossible to access bus values when "ready" bit is down (Nothing case). You get rid of another class of mistakes.

For this to work in more or less usable way, you have to be able to specify in type level equalities like "concatBitVectors :: (rlen ~ Add alen blen) => BitVector alen -> BitVector blen -> BitVector rlen". This is just not possible in Java. It is possible in C++, but C++ lacks algebraic types like Maybe and more. It is possible in Scala, but Scala has its own pecularities (modifiable variables are absent in hardware).


It is not comparable. Haskell's type system is a qualitatively different thing from Java's, with different use cases (it can be used the same way as Java's, but people just don't).

Java's types don't help you organize your code, don't help you make it more concise, and enable only the shallowest kind of code generalization. They are not expressive enough to prove correctness, they mostly do not help you hiding information away from the developers focus, and they mostly do not allow you to restrict code into their responsibility.


I feel like it's hard to give a concrete practical code example, but maybe I can describe my practical experience.

The main difference I've experienced is that while java's type system forces you to be explicit about your types in a lot of places – like implementing interfaces, assigning types to variable declarations, and just in general the fact that "type inference" is limited to expressions – you get very poor checking of those types, since a lot of their complexity is hidden in the object hierarchy. This in turn, is due to java's orgins as a object oriented language relying on subtyping and inheritance for polymorphism (generics improved somewhat on this.) The result is that a lot of the complexity that haskell gets accused of, ends up in complex design patterns and/or object oriented design principles in java. This has gotten better as java has loosened some of its initial restrictions (e.g. java 8 allowing first-class functions.)

Haskell on the other hand was designed with parametric polymorphism (generics in java terms) in mind and as a functional programming language with first-class functions and no object orientation, allowing it to reap more of the benefits from the more theoretical research into type theory and category theory (yes, this gets us into monads, but I don't think they are nearly as mysterious as the internet makes them out to be.) In my opinion this has made the abstractions in haskell a lot more sturdy and more importantly statically checkable, compared to the object-oriented design principles underpinning a lot of design patterns in java. Haskell also has global type inference, which means you can avoid explicit types in many cases, especially when prototyping small, pure functions. This benefit is somewhat lessened by the fact that haskell's error messages can get very complex, but I subjectively believe that this is due to the fact the type system is checking a lot more and a lot more of what gets checked doesn't have to be given an explicit type by the programmer.

Given this I pretty clearly prefer haskell, but I've spent most of my career writing java and php. In fact, most of my criticism of java drove me to dynamic languages at first (although I would have preferred python over php.) What got me interested in haskell was the fact that I felt that there should be a way to have the freedom and speed of developing in a dynamic languages, while having the same (or better) guarantees of a statically typed language. This what led me to read about type inference.

Now, the complexeties of haskell (or even worse, haskell with ghc extensions) hardly makes my dream a reality, but I still feel like I write a lot less types while having the compiler do a lot more work for me. What has made my dream more of a reality is actually elm[0], which has similar theoretical foundations as haskell, but only has has generics (not interfaces/type-classes like java/haskell.) It's a language in which you can just write your code without types like a dynamic language, rapidly iterate on it and then add a type signature when your satisfied with it. (That's almost what I do in haskell as well, but I can run into more complex problems.)

(This characterisation is probably colored by the period I used java most heavily and might be slighty unfair, but I also limited the description of haskell to the most basic features which it has had since the 90s.)

tldr; mmm, delicious global type inference..

[0] http://elm-lang.org


A better type system != better software.


as others have already said Haskell's type system is more powerful. however more powerful does not always mean superior. Java strikes a balance between flexibility and ease-of-understanding, whereas Haskell allows you to construct the most convoluted mathematical abstractions imaginable. which is probably why Java is so popular in the enterprise and why many successful newer languages essentially copy its type system.


Java's types become incomprehensible once you start trying to do anything complex with generics.

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.


What is the state-of-the-art for Haskell IDEs? The last time I was doing Haskell in anger, I was a college freshman using GHCI and, I think Geany, which was slightly a nightmare. I would expect that there ought to be some pretty powerful stuff nowadays.


I personally use VSCode with the Haskell IDE Engine as a backend.

It's definitely not as nice as something like Visual Studio or IntelliJ, but it's not too bad.


Standard coding practice is to write type signatures for functions.


Haskell's type inference (and type system) are leagues ahead of Java.


And Java's market share and ecosystem is leagues ahead of Haskell.


> the bottom line: it's just not that great for newbies. since most people are going to be newbies at it, i could not recommend it at all. sometimes i think the language even goes over my head, and I'm supposed to be a pretty smart cookie.

mmm.

> If i have to recommend something now it would be python. because it's easy and because i started using it for my personal stuff. i know lots of languages and that's what i end up coming back to if i need to do stuff quickly.

Python and Haskell are useful in completely different domains.


at the train station we have some Haskell application which does one thing: it does accounting of the number of free and parked bicycles in each rack. in this case a comparison with another programming language is useful.

my comment is necessarily about applications where a comparison is useful, not those specialized financial applications at investment banks where Haskell is popular for undoubtedly good reasons i have absolutely no clue about.


By 'different domains', I don't think he was implying specialized financial applications as the only good domain for Haskell.

Haskell is a very good general purpose programming language for the reasons the commenterd gave in the thread. It is great for all kinds of general backend tasks. The kind of tasks one would associate with Java would also be a great for for Haskell.

Python is also general purpose. It's dynamic typing is especially good in specialized domains of rapid prototyping and exploratory data analysis (perhaps useful at investment banks too).


> most people are going to be newbies

Only briefly; I expect to be proficient with a tool for most of my time with it. If I constantly find myself near the bottom of the learning curve, that means I'm impulsively choosing and abandoning tools way too quickly for the payoff.


> it's just not that great for newbies

At the other hand, if you filter your hires by people that know it, you are assuring you won't get a newby.


If introducing a functional language was the aim (EDIT: that's my reading of the motivation here) then, given the political context described, I can't help but feel a better choice would have been F#.

It ticks, or half ticks, most of the points in the "Benefits of Using Haskell" section. Whilst also coming armed with C# interop and integration with the .NET ecosystem in which they were already invested.


In my experience, languages that try to bridge OO and functional ecosystems (F#, Scala, etc) tend to suffer from a lot of split-brain / "worst of both worlds" syndrome. You miss a lot of the advantages of FP unless you go all-in on it like Haskell does.


My experience with F# is that functional programming is the default paradigm while object oriented is used when it is required or easier (or required by a C# library you really want). A striking difference with the little Scala I read in the wild (where object oriented was the clear default).

The same goes for mutability, it is there and you should certainly use it when it makes sense but it is not the default.


> The same goes for mutability, it is there and you should certainly use it when it makes sense but it is not the default.

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 has confined mutation with the State and ST types, which guarantees that whatever may be going on inside, the external interface to the function is pure. My main problem with F# (and other multi-paradigm / "functional-first" languages) is that they do not provide any such guarantees; purity becomes merely a matter of convention and convenience, not something ensured by the language. This misses the entire point of functional programming, IMHO, which is referential transparency, and greatly increases the complexity since there are things that matter in F#, like evaluation order, which purity renders completely irrelevant in Haskell.

(Yes, Haskell does have unsafePerformIO and the like for special cases, but the expectation is still that the external interface remains pure. If you deliberately circumvent the language's protections and fail to adhere to this rule then you get to keep both pieces when it inevitably breaks. The compiler is still going to operate under the assumptions that the result depends only on the explicit inputs and that evaluating the function has no side effects.)


> You miss a lot of the advantages of FP unless you go all-in on it like Haskell does.

I'm not familiar with F# but Scala at least has a far inferior compiler (compared to GHC). There are a lot of functional techniques that simply don't make sense when you don't have dedicated tooling to support them.


My thoughts exactly. I'm curious what compelled the author to choose Haskell over F#.


If I recall, F# doesn't require managed IO which just opens up a can of debugging worms to where you have no guarantees of where side effects and impurity are happening.


I'm not familiar with F# but from what I understand it lacks support for laziness, unlike GHC.


I think this is Haskell's biggest disadvantage in industrial sized applications because it significantly complicates debugging and performance reasoning.

Laziness is, in my opinion, the wrong default.


> complicates debugging and performance reasoning

Lots of people say this, very few understand what it actually means and how to do the analyses.

> Laziness is, in my opinion, the wrong default.

Unfortunately, GHC is still the only compiler with first-class support for laziness as well as strictness. And you need both if you want to be able to do immutable functional programming.

But in the grand scheme of things it doesn't really matter if you know what you're doing when you use data structures. Some data structures are meant to be strict, others lazy. Haskell allows you to create data structures that are strict in the right places fairly cheaply.


As a counter to this that may make it easier for a company to adopt and reduce the learning curve. Laziness can make it harder for some to reason about performance as an example.


> Laziness can make it harder for some to reason about performance as an example.

Lots of people are fond of pointing this out, but very few are actually able to reason about performance of lazy data structures.


The language does support laziness, it is just not the deafault.


The default is the whole point. Almost any language can support lazy evaluation, given enough boilerplate, but laziness-by-default is a major contributor toward making Haskell code more composable and reusable compared to idiomatic code in other languages.

In strict-by-default languages one must decide up front whether to permit evaluation to be deferred, and there is a cost to be paid via more awkward syntax to first capture the deferred computation and then explicitly evaluate it. This also tends to add runtime overhead which a Haskell compiler would optimize out in cases strict evaluation can be inferred. As a result, libraries generally expose only strict interfaces—and while most lazy functions can easily be made strict in Haskell with judicious application of `seq`, the reverse is not so simple.

Sure, sometimes excessive laziness becomes a problem. However, these cases are not that common, or particularly difficult for an moderately experienced Haskell coder to identify or work around. Enforcing strictness-by-default just because one does not foresee a need for laziness, without any evidence that laziness is negatively impacting performance, would be a form of premature optimization.


Don’t forget the importance of Microsoft’s approval, that carries a lot of weight.


And if you ever want to convince a manager that F# could make a difference in productivity/safety/... : http://fpbridge.co.uk/why-fsharp.html


Which points do you believe that F# doesn't tick, or only half ticks?


If I'm a manager, and somebody tells me that the development team wont be productive for months, I'd likely ask for some real metric indicating that Haskell solves / eliminates classes of bugs untouched by other statically typed language.

At least some figure indicating that a Haskell app is less prone to bugs, etc.

Otherwise why not throw Typescript at it?


I'd probably rephrase "not" to "less". Haskell is sufficiently unlike other languages that a lot of knowledge/skills that are usually transferable between languages don't apply to it. That means you need to (re-)learn how to solve those problems in Haskell if you want to use it.

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.


yeah it sounds like it. One day I’ll actually dive in and learn that stuff.


The "not productive for months" is a exaggeration.

Even non-trivial type-level programming can be picked up by complete novice in Haskell in less than month. I experimented with that.


Please don't do it, unless you know you are going to stay there (in the same project) for very long time and you know you can hire/retain and train new people in Haskell.

I work for a large MNC bank and in my prev stint with a different department, for whatever reason I had to inherit a not-so-trivial Haskell code-base which gave me really hard time. Although it was in BAU mode, maintenance was difficult and hiring was even more difficult, I couldn't even get help from other guys from different projects as they are all mostly Java guys, anyway I moved and I know the new manager is trying hard to convince his boses and business for getting fund to migrate it to Java.


I might know your bank, do you run three versions of Murex at the same time? They have a pretty strong Haskell team (though somewhat small, 10s vs 1000s of Java devs), but that's what's at the core of the article. The writer seems very keen about developing and coaching a Haskell culture. So, as you say...

> unless you know you are going to stay there (in the same project) for very long time and you know you can hire/retain and train new people in Haskell.


Unless there will be many capable developers who stay. If you're the single guy who has a clue then yes, don't do this if you don't have a reasonable plan for those who stay.

It also sounds like maintaining a haskell code base is some rocket science. It is not. There are both extreme, but also conservative ways of doing things, and if you pick the conservative, then the people staying won't have that much trouble coping.


Please don't get me wrong, I've been in programming for more than 13 yrs, started with C++ and moved to Java later in my career and that Haskell code is of top notch quality, it does what it was written for very well and if I remember correctly, it never caused any prod incidents, its just that the devs didn't stick around, one of them went to Uni and others to greener pastures and we found it hard to extend/enhance with new functionalities that business was asking for.


I am available if your company needs consulting services for Haskell. I can help with development, design, maintenance, and training. If you would like to learn more, please email me at consulting@jamesparker.me.


Thanks, I'm no longer with the project, but I'll mention it to the one who is taking care of it, but last I heard was they were looking to migrate to Java or integrate some of its functionalities to another system.


Yep let's bring a language into a company where:

- it's very hard to hire people

- lack of libraries

- lack of support / community

- difficult learning curve for the language

Where I work some teams are dropping Scala because hiring Scala dev is hard, so imagine Haskell...


Teams hiring developers versed in specific languages, libraries, databases, http servers, deployment orchestrators, etc are doing it wrong.

Hire good developers. They will learn whatever technology your company uses and/or built.


I think this is the wrong mindset.

A better one would be: "Hire good developers. You can invest in teaching them whatever technology your company uses and/or built."

Otherwise you end up with companies that hire good developers who don't know the tech stack and expect them to be 110% productive in one week with no investment from the company in training them. Then, even if the developer can keep up with demands they end up writing sub par code due to unfamiliarity with the tech stack.


That's probably a better way to phrase it.


Pretty expensive, to be honest. Facebook snatches up most of the "engineers" and blockchain companies hire a lot of the academic community.

That being said, if you have the money, Haskell developers will absolutely follow - and in some domains the project will actually be cheaper.


The executives who think good developers are "expensive" are generally happy to throw gobs of money at BPO firms to do the job half as well as in-house staff for twice as much money.

Besides which, an employee with a fully-loaded cost of $200k/yr can be sent to a one-week external class for well under $15k including salary, tuition, travel, and expenses. That's far less than the cost of acquiring and onboarding that employee; and if you don't care to train your staff, they'll jump ship for an employer that doesn't suck the stars out of the sky.


You can absolutely get some top-tier Haskell talent for $200k/year :)


Your second and third points are just wrong.

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.


From my repeated personal experience, hiring decent programmers and teaching them Scala is not hard.


cant you just write scala as a simpler java? why is it hard?


What is replacing Scala? Kotlin?


In terms of people moving away from java, I would say yes. It’s a smaller leap than Scala and an easier sale to management. Quite a lot of teams that have moved to Scala have struggled, mostly around supporting the new shiny services that have been written by guys who have moved on. The TCO from my observations seems to be higher than for java. To give some context I’ve never been a fan of java.


Somewhat related. How do you introduce any language?

How do you get past writing anything that isn't java,c/c++ and python without being a cowboy. In my short experience writing with any other language gets a somewhat negative response.


"How to trick a company into adopting a language that is difficult to hire for and has a small ecosystem"

If FP is the goal, then Clojure and F# would be FAR better suited.


As much as I like Clojure (and Racket/Scheme/Lisp), it's a dynamically typed language and is a nightmare to work with on a large scale project - similar to Python. Those languages are much better suited to small projects. F# would have been a fine choice, but I think Haskell was an excellent choice despite its initial drawbacks.


Believe it or not, it wasn't that long ago that Python was that weirdo language nobody uses.


I mean yes but it's no longer true. It's ridiculously easy to get a job on the basis of "yeah I can do Python".

My current challenge for my next job is to get an opportunity to work with Go professionally, because try as I might deploying Python reliably remains a colossal pain in the lower.


But the programming process in python feels like cheating sometimes :)


And nothing is hinting that Haskell will become a mainstream language. It's an unnecessary risk for a business to take.


This was an interesting read but the "some people didn't like this and thus left" left a sour taste.

I'm a big fan of team decisions for tooling and languages used and I'd personally have some problems if someone told me we'd be switching languages next month. Well, unless I already knew the language and/or tried and liked it - but that's just a random coincidence that I like using and learning a lot of languages.


I should have been more clear. People left due to their unhappiness with the company merger, not the development team merger specifically.


As the OP I am happy to see this post make its way to HN. I hope the contents have helped people/teams willing to take something positive from it.


It's a wonderful write up, thank you!

We should have more of these from seasoned developers. There are a lot of hard core math/type theory guys on reddit and elsewhere (who I have lots of respect for), but in an industry setting there are (1) features to deliver and (2) people to be dealt with -- outsmarting has little place with those. You have apparently succeeded in doing the jump in this setting.


Haskell is fantastic. In fact, it is by far my favorite language. Strict types and functional programming come together in a perfect union. Monads are very similar to JavaScript callbacks, actually. After extensive use of the language, I finally decided to give it up for 2 reasons. 1) Stack and package management. Specifically, after building many websites with Haskell's "supposedly" production ready framework, Yesod. After an upgrade, every site I made completely broke and there was almost no documentation on any version changes for this framework. Which leads me into complaint 2) Lack of good documentation. I'm not trying to take sides on the debate of self documenting code, however, when using higher level libraries, it is completely infeasible to rely on reading source code to determine what a function does. Haskell programmers believe that because of such strict typing, the code should speak for itself. Unfortunately, the real side effect of this is you end up coding trying to match up your types instead of focusing on your goal at hand.


I've done something very similar, albeit with a more bottom-up approach. Pretty much everything he's suggesting is good advice.


Benefits of using haskell

- Reduce programmer cognitive overload

I don't know how he could honestly say that. Haskell is much more cognitively demanding than other languages from my experience

A lot of the benefits he talks about he could get from F# or Ocaml, which are much simpler to learn and use for a team

That being said, I think haskell does have unique niche in industry: if the company does something very complex and cognitively demanding and requires the best and the brightest, using haskell can be a way of luring the best and brightest to work there


When we say "reduce programmer cognitive overload" we are usually talking about purity.

  f :: A -> B
There is nothing ambiguous about this function when considering application state and IO. You cannot call fireTheMissiles inside it, it performs no side effects. It simply takes an A and returns a B.

The headphone rule always comes to mind when talking about this. Typically developer productivity is killed when a developer is interrupted because they are trying to maintain a complete picture of time and space in their head. This problem is much less so with Haskell because you can just glance at the inputs and outputs of the function you were working on and get back on track immediately.

In the sense that you are implying, that the language itself is cognitively demanding, I would argue that is only a beginner problem. Once the core concepts are internalized it's actually very easy to use.

Where it gets hard and becomes a mental burden is when you start going off the map and looking into some of the more advanced concepts, like type level programming, which to date we haven't had to pay attention to or use on my team.


If you're talking about purity then I'd agree with that, but I'm talking about haskell as a language.

I'm definitely not a haskell beginner, and I know others who are definitely not beginners and they feel the same way.

I'm talking about the language as a whole. With all of the extensions available, there's plenty there for even seasoned haskellers to learn. Sure you can get used to anything, but I've found the more advanced type features, and higher kinded polymorphism, to make code and type errors harder to reason about. Sometimes type inference screws up in ways that makes it hard to figure out whats going on.


> Haskell is much more cognitively demanding than other languages from my experience

How?

I think Haskell code can be overcomplicated sometimes, but that's not mandatory.


If you have internalized the concepts Haskell is built on (to the point that you don't have to think about them), then Haskell can be as simple as any other language, maybe even simpler. But if you have to still have to think about the underlying concepts, Haskell probably is more cognitively demanding.


That's exactly the point, yes. People just have to properly learn the language.


I'm not sure it's that simple. I suspect (but cannot prove) that some people are naturally procedural thinkers, and others are naturally functional thinkers. Haskell just makes sense to some people - and not to others. To say they "just have to properly learn the language"... I could say the same about you and C.

Assuming I'm right, can the naturally procedural thinkers really learn to use Haskell? Probably yes, at least most of them. Will it ever be as easy to them as procedural programming? Probably not. What will that "not as easy" look like? Greater cognitive load.

I am aware that all of this depends on my opening assumption being correct...


That's an interesting assumption.

It might be true to a degree, yet I reckon the problem lies in CS teaching. A vast majority of programmers seem to start with imperative languages, hence they are more familiar with the procedural paradigm, and when they encounter functional code it seems alien and difficult to work with.

That's why I wrote people “just have to properly learn” functional languages. But your hypothesis is probably true as well.


"will not be productive for months" is probably going to be instant deal breaker from about 98% managers.

Also, another big responsibility is teaching the rest of your coworkers. Classes, hackathons, documentations, etc.


Absurd.

The bulk of being a good-engineer is productivity, by reinventing the minimal amount possible. Highly efficient engineers are very accustomed to their tools (IDE, language, framework, database and DB drivers, webserver, deploy system, logging).

Forcing a team of engineers to use a new language, IDE, framework, particularly one that has minimal backing, is something I would consider a "fireable" offense (i.e. costing the company hundreds of thousands of dollars for personal amusement).

And also, if you did want to go functional, why not something used by literally any professional company? E.g. Twitter on scala.


> why not something used by literally any professional company

Can we cool it with using "literally" to mean "figuratively"? You may have heard of Facebook or Standard Chartered for instance, unless you consider them both unprofessional. Sure, it's less common than other FP languages, but Haskell is used for non-trivial things by non-trivial companies.


I meant literally, but by professional I meant "A-tier." I know of zero billion dollar software companies that use Haskell as their primary development language.

I know nothing about Facebook using Haskell. Last I checked they use a PHP-derived language called Hack.


Haskell is being used for their spam filtering system, Sigma: https://code.fb.com/security/fighting-spam-with-haskell/

I'm not sure what else they use it for, but they hired Simon Marlow, one of the main guys behind GHC a years ago. It's still not their primary language, but restricting the interpretation of "professional" and "uses" to what you had in mind is not the most interpretation of your comment to me.


Maybe I should preface that by saying I'm not a big fan of Scala...

But I think Scala has the major problem that Perl has, take 5 developers and you get 6 different styles. I went from "Scala is horrible" to "oh, this actually looks nice" to "omg, what the hell" and so forth. Look at a random library as a beginner and think "is this really Scala"?

And that's even ignoring the problems with sbt, binary compatibility, and so on. Yes, there were some success stories. Also some stories of replacing Java with Scala, but I've heard nearly as much "well we replaced it but we don't know if it's really better".


Seems like a very weak justification to me. I'm sure it's easier to hire an engineer who can write idiomatic scala than idiomatic haskell.

But all that is aside from my main point, which was changing tools on people is almost never justified. Unless you're writing a web app in ASM, you usually should stick with your language.


I do think your analysis here is a bit shallow.

- Scala is not an easy language to learn unless you just use it as a "better Java" with syntactic sugar, in which case it cannot be considered to be in the same class as Haskell. The same is true of many other languages folks are proposing, like Clojure or F#. It might be easier to bang something out with Clojure than Haskell, but I don't think it's any easier to master than Haskell.

- Your estimate of the cost (hundreds of thousands of dollars) assumes there's no benefit to the switch. There may or may not be, but you didn't even account for that possibility.

- Highly efficient engineers are also efficient at learning new tools, frameworks, IDEs, etc., because for many developers that's part of daily life.


> Scala is not an easy language to learn unless you just use it as a "better Java" with syntactic sugar, in which case it cannot be considered to be in the same class as Haskell.

The question is how you get to there from here.

6-8 years ago I wrote "better Java" style Scala. For the last couple of years I've been writing Haskell-like Scala and enjoy all the cited advantages. But, crucially, I was able to remain productive the whole time, and do all my learning on the clock while working on real, useful projects. Nowadays I could probably get by in Haskell (I would still choose Scala over Haskell, but that's a separate discussion), but if I'd tried to start with it in the first place I would never have got off the ground.


I'm not necessarily arguing in favor of a team being spontaneously switched to Haskell (any big move like that seems ill-advised in general), but I do find this overall line of reasoning a little unconvincing. You're suggesting that you'll only learn something if there's a smooth, continuous path to its mastery from what you already know. That basically leaves you stuck in whatever connected component of programming expertise you're already in, incapable of making a big jump anywhere else.


> You're suggesting that you'll only learn something if there's a smooth, continuous path to its mastery from what you already know. That basically leaves you stuck in whatever connected component of programming expertise you're already in, incapable of making a big jump anywhere else.

Indeed it does, but I think it's the right choice. How many times can you afford to "not be productive for months" for the sake of learning some new paradigm that promises the world - and how many actually deliver on what their advocates claim? There are dozens or hundreds out there, and while I now know from experience that the advantages of Haskell-style functional programming are real, a priori there was no way to distinguish it from all the oversold-but-useless approaches that are out there. Indeed my experience is that whether you can do it incrementally is actually quite a good signal for whether there's real value in a paradigm, or it's a load of hot air.


Scala is absolutely easier to master than haskell. Source: learned scala with no java experience and then picked up haskell for a while.


This sounds like constraints for a suit-and-tie company where programmers and teams don't have much autonomy. Maybe this is your definition of a professional company. In other kinds of settings, the stars may align in favour of non-mainstream languages. If your project has to attract good programmers from inside the organisation and a modicum fearless propellerhead attitude is part of the culture, it may be worth it. But of course forcing a team to adopt anything should not enter the picture.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: