
Haskell Is Exceptionally Unsafe (2012) - kirkbackus
http://existentialtype.wordpress.com/2012/08/14/haskell-is-exceptionally-unsafe/
======
jonsterling
As others have said, it's not nearly as bad anymore as It was when Bob wrote
that post, but I would say, please do not take that as a reason to not take
what he says very seriously. I use haskell because it is a very practical
tool, (bona fides: I am an experienced haskell developer and I actually use it
full time for my job---not an armchair evangelist) but it has become very
clear to me that the next great thing will be more like ML than like Haskell.
There are of course many important lessons to be learned from Haskell though!

~~~
berdario
Since there aren't a lot of full time Haskell developers, I'm curious to know
what do you use to setup your projects and handle dependencies:

hsenv, cabal-dev, cabal sandboxes, nix, stackage ... or do you include
everything in your repository (any tool to automate that)?

~~~
Ixiaus
Full-timer here. I use cabal sandboxes heavily and recommend you do so.

Nix is great but you have to take some time to set it up and learn it -
sandboxes are pretty standard and work as you would expect with ghc-mod (not
that Nix doesn't I just had more time invested in getting it and the tooling
setup to use it as a "dev environment" \- cabal sandboxes are much simpler).

Stackage is great too, btw.

~~~
berdario
Thanks. Since we got the ball rolling (I planned to ask it on some mailing
list, but I kept procrastinating to write a semi-formal mail).

Do you know of any way to use multiple stackage repositories? (for now it's
not a problem, but I envision a future when I'll have dozens of projects, and
updating everyone of them to use the same library versions might not be
feasible)

I know that I can `cabal --config-file=/path/to/cabal.config` but I'm
wondering if there's an easier way and/or any convention

I'm especially worried of forgetting something (like reusing the same ~/.cabal
for multiple stackage-cabal configs)

~~~
Ixiaus
I haven't actually tried to use multiple Stackage repos. I only think it's
great because I helped a friend get started in Haskell and chose to see if
Stackage would help with his cabal hell woes (it did and made the experience
more pleasant).

In general though, I think stuff like Stackage is a community smell and has
the potential for creating a schism and confusion in the community. If it's
community infrastructure I also feel like it should be controlled by
haskell.org and not a for-profit company.

I know I know, money and man-power are all issues but other OSS languages have
successfully figured it out and I think Haskell can too.

I personally use Nix for everyday development.

------
carterschonwald
I'd like to point out that the example at the end of the blog post is only
runnable in GHC 7.6 and Older. As of GHC 7.8, you can't define your own custom
typeable methods, you can only ask GHC to derive a typeable instance

------
wyager
>The most blatant violation is the all too necessary, but aptly named,
unsafePerformIO

The only time it's necessary is when you're using the FFI or working with
language internals, at which point there's really no way for the type checker
to work anyway.

One should avoid using exceptions in pure code. This is well established.
Instead, use any of the many type-safe exception mechanisms, like Maybe or
Either. Having written probably in the high thousands or low tens of thousands
of LoC of Haskell, I've never once used a user-defined exception or undefined.

The point of this article seems to be "If your code breaks, it's no longer
type safe.". I don't think this is news to anyone.

~~~
rspeer
It's the kind of unhelpful, overly simplified dismissal that HN is known for.

You should recognize that your opinions about how people _should_ use your
favorite programming language are not "more or less objectively true".

Context: the post I'm replying to used to end with a complaint that people
would downvote something that's "more or less objectively true", and a request
that people should explain why. I can't downvote, but I can explain.

~~~
wyager
The fact that people should use good coding style _is_ "more or less
objectively true". I'm surprised _that_ is the part you take issue with.

How is this dismissal overly simplified? What have I failed to take into
account?

------
bjterry
There was some discussion on this topic a while back which I remember. For
convenience, it is linked here:
[https://news.ycombinator.com/item?id=4380900](https://news.ycombinator.com/item?id=4380900)

------
tailrecursion
I want to question the importance of soundness in type systems. Suppose you
could catch 99% of type-based errors instead of 100%, and in addition, use a
compiler switch to see all the case statements where a class of a type is
missing. The intended benefit of this system is that it accepts all correct
programs. Correct meaning, the program runs and returns the correct answer.

Would such a language be viable? Or is it absolutely necessary to catch all
possible type errors. In the past, tools like lint have been considered
useful, although lint is not at all the kind of type system that I envision,
namely a system that is in practice catching all the errors that ML catches --
it just doesn't (and cannot) guarantee it catches them.

The restrictive nature of static type systems today is legendary, but I wonder
sometimes whether people realize how restrictive they are. If you can't make
your idea work with functors or typeclasses, chances are good there's no way
to get it to compile and you have to write functions in longhand.

~~~
shadowfox
There is always idea of Gradual Typing [1] which has been implemented with
varying degrees of success. There are also a large set of static analysis
theories/tools which can help here.

It is also worth noting that if you dont want (global) type inference, you can
get far in a language with permissive casting, type annotations and local
inference. The results aren't a panacea though.

> Suppose you could catch 99% of type-based errors instead of 100%, and in
> addition, use a compiler switch to see all the case statements where a class
> of a type is missing.

I am not quite sure what you mean by this. Care to elaborate? (In general,
with inference systems, missing type information is hard(ish) to localize. So
pointing out where exactly a type error occurred is non-trivial)

[1]
[https://en.wikipedia.org/wiki/Gradual_typing](https://en.wikipedia.org/wiki/Gradual_typing)

~~~
tailrecursion
I'm thinking of a system with valueset inference where valuesets are not
necessarily disjoint. So the system may infer that a return value is the
disjunction {INTEGER | REAL}.

In order to get precision in checking, a lot of computation needs to be done
so the compiler relaxes the precision when facing large disjunctions
(networks) of constraints.

Dynamic checks are inserted as necessary but a system that relaxes when things
get hairy can't guarantee that it will find all errors at compile time.

The idea is similar to Soft Typing of Cartwright and others, but they were
thinking of an interactive system, some kind of programmer's aid. If I recall
they ran into problems giving reasonable error messages.

~~~
tomp
The problem with this idea, at least compared with current implementations of
Haskell and OCaml, is that it requires runtime type information. Right now,
Haskell and OCaml both perform erasure, and the only kind of runtime type
information used is for the GC, but if you have two ADTs with identical
structure (number of branches, payloads) but different names (i.e. they are
different types), they will be encoded in the same way. So, in order to tell
them apart, you would need some additional type information, which would
require changes to compilers and would probably performance characteristics.

------
coolsunglasses
Harper's an accomplished person in CS and has done great work, but he's not
putting a good argument forward here.

I've talked to Harper about this post and his opposition to Haskell before. I
mentioned that it was leading people to believe they could ignore typed FP,
not redirecting to an ML derivative. Harper expressed dismay at this.

There are more advanced languages than Haskell, they aren't ML, and PL
researchers/experimenters are still working out how to make them work nicely
for day to day stuff.

First:
[http://www.cs.ox.ac.uk/jeremy.gibbons/publications/fast+loos...](http://www.cs.ox.ac.uk/jeremy.gibbons/publications/fast+loose.pdf)
(This isn't a throw-away reference, informal reasoning has worked extremely
well in practice. Yes, I'm making _that_ argument as a user of a pure, typed
FP language.)

unsafePerformIO is primarily used to change thunk-memoization behavior [1].
Also, it says unsafe right on the tin. Nobody uses it in practice in ordinary
code. It's not something you have to incorporate when reasoning about code.

Giving up reasoning about your Haskell code as if there were semantics-
violating unsafePerformIOs lurking in the depths is similar to giving up
reasoning about any code because a cosmic ray might flip a bit.

Lets consider the rather remarkable backflips Standard ML and OCaml had to
perform in order to make FP work with strictness and impurity.

You can ignore unsafePerformIO because very very few people ever need it and
you'll almost never have a reason to use it. Just don't use it.

Similarly, writing total functions is the cultural default in Haskell. The
compiler warns on incomplete pattern matches which you can -Werror as well.

You can't define your own Typeable instances as of GHC 7.8 - only derive them,
so that soundness issue is gone. Typeable itself is not popularly used,
particularly as SYB has fallen out of favor. One critical aspect of why I like
Haskell and the community around it is the willingness to fix mistakes.
Meanwhile, ML implementations still use the value restriction.

>the example once again calls into question the dogma

Oh please. Haskell is an ensemble, multi-paradigm language with the right
defaults (purity, types, immutability, expressions-only) and escape hatches
for when you need them.

Haskellers appreciate the value of modules a la ML, but typeclasses and
polymorphism by default have proven more compelling in the majority of use-
cases. There are still some situations where modules (fibration) would be
preferred without resorting to explicit records of functions. For those cases,
Backpack [3] is in the works. It won't likely satisfy serious ML users, but
should hopefully clean up gaps Haskell users have identified on their own.

Harper's case is over-stated, outdated, and not graced with an understanding
of how Haskell code is written. Informal reasoning works if the foundations
(purity, types, FP) are solid.

[1]:
[https://github.com/bitemyapp/blacktip/blob/master/src/Databa...](https://github.com/bitemyapp/blacktip/blob/master/src/Database/Blacktip.hs#L47-L54)

[2]: [http://caml.inria.fr/pub/papers/garrigue-
value_restriction-f...](http://caml.inria.fr/pub/papers/garrigue-
value_restriction-fiwflp04.pdf)

[3]: [http://plv.mpi-sws.org/backpack/](http://plv.mpi-sws.org/backpack/)

~~~
eagle2001
"There are more advanced languages than Haskell, they aren't ML, and PL
researchers/experimenters are still working out how to make them work nicely
for day to day stuff."

Examples, please. (I like bright, shiny things.)

~~~
Chinjut
Perhaps Coq, Agda, Idris, and other such dependently-typed languages are to be
considered, at least in some dimensions, "more advanced" than Haskell.

~~~
mercurial
I wouldn't say full-blown theorem provers (Coq, Agda) are really in the same
category as Idris, which is supposed to be more practical.

~~~
tel
Why not? I'd say that Agda/Idris/Coq are substantially the same languages with
variation arising only in the kind of styles of coding they emphasize.

~~~
mercurial
But isn't this a variant on the old "but it's Turing-complete, therefore you
can do anything" fallacy? Sure, their type system may be similar, but the
question is, which one will let you write, say, a robust, maintainable HTTP
client with the least amount of pain?

~~~
tel
I suppose that's true. I guess in my eyes DTs are such a meteoric difference
that Idris is not sufficiently more interesting than the others yet. But time
will tell if they manage to build a better way to manage proofs, for instance,
they could really change the game.

~~~
coolsunglasses
That there is no game-plan for doing anything any better than Coq presently
does is why I'm a bit skeptical. The trimmings are nicer - nothing else as of
yet.

~~~
freyrs3
The elephant in the room in these discussions is that the cost of bringing a
function compiler to fruition is so high that too much of the discussion gets
muddled in the semantics of these hypothetical Haskell-successor languages
while no one is actually working on said language. Academia simply isn't set
up to incentivize large engineering projects, and industry would never invest
in building such a thing either since there's no profit in language dev sadly.

The blunt truth is that at the end of the day Haskell works today, period, and
until someone actually forks or starts writing a new language very little of
these criticisms of Haskell actually matter if the answer to "what should I
use for my project at work" is "well it doesn't exist yet, but it has modules
and extensionality and a magical pony that shits money".

~~~
coolsunglasses
This is more or less where I stand as well. Haskell has an efficient RTS, well
designed compiler, best-in-industry concurrency, good-enough type-safety that
is light-years ahead of even things like Scala, and a good library ecosystem.

It's ready _now_ and I'd like to begin work with Haskell in the hopes that
industry wakes up to the utility of future successors to Haskell by seeing
Haskell itself in action.

------
accessright
So basically it is "unsafePerformIO" and "error" that is the problem?

So if you do not use them (which I never do and it is recommended not to) then
the problem is not relevant?

~~~
densh
I think the main problem here is that it's not just you, but also your
transitive dependencies.

------
reirob
Here the reddit thread about this article, from 2 years ago:
[http://www.reddit.com/r/haskell/comments/y74vn/robert_harper...](http://www.reddit.com/r/haskell/comments/y74vn/robert_harper_haskell_is_exceptionally_unsafe/?already_submitted=true)

------
qwerta
Being unsafe never stopped Ruby or PHP, while Ada is still nowhere.

~~~
Horusiath
Tell that next time you get on the plane.

