The darker corners of throwTo

We will assume

in the remainder of this post.

The documentation of throwTo states

Whatever work the target thread was doing when the exception was raised is not lost: the computation is suspended until required by another thread.

We can observe this directly when using  unsafePerformIO :

The test starts by spawning a new thread that begins summing the 37th down to the 31st Fibonacci number by demanding the value of the foo = unsafePerformIO fooIO  thunk. After half a second a second thread is spawned which blocks on the same thunk, and will wait for the first thread to finish. Consider, however, what happens when we then kill the first thread (the cancel function from async throws an asynchronous ThreadKilled exception to the destination thread): the second thread seamlessly takes over the computation of the thunk. Compiling the above example (without any ghc options) and running it gives

Nice. But now consider what happens when we replace  fooIO by

Since no IO exception is ever thrown, you would think that this should make no difference right? Wrong:

What happened?  catchIOError actually catches all exceptions, not just  IOErrors; however, it then re-throws all other exceptions. fooIO_1 is actually equivalent to

The asynchronous exception thrown by  cancel is caught and then rethrown as a synchronous exception. This synchronous exception is not caught, and becomes the final value of the  foo thunk. Hence, when the second thread takes over the evaluation of this thunk, it finds the exception and gets killed.

So what if we want to catch IO exceptions, and deal with them, but still be able to rethrow asynchronous exceptions? Is there a way? Well, yes, we can rethrow the asynchronous exception again as an asynchronous exception. From the documentation of throwTo  again:

If the target of throwTo is the calling thread, then the behaviour is the same as throwIO, except that the exception is thrown as an asynchronous exception. This means that if there is an enclosing pure computation, which would be the case if the current IO operation is inside unsafePerformIO or unsafeInterleaveIO, that computation is not permanently replaced by the exception, but is suspended as if it had received an asynchronous exception.

But then we have to specify precisely how to continue after the rethrow:

However, this code is not equivalent to the version without any catches at all, because we now explicitly restart the computation after the asynchronous exception:

(Note that the computation starts back at 37 after “Killing a1″.) I don’t think that there is a way around it (but if there is, please let me know :) ) The other problem with fooIO_3  is that it is rethrowing all exceptions asynchronously; unfortunately, there is no way to reliable detect if an an exception was thrown synchronously or asynchronously, since throwTo  can be used to throw any kind of exception (see ghc bug 5092). At the moment, probably your best bet is to rethrow AsyncExceptions asynchronously and the rest synchronously, but that’s a “best effort” only and may break. If you are using HEAD, you can do slightly better, because there is an ‘asynchronous exception hierarchy’, based on a SomeAsyncException  data type analogous to SomeException ; however, that still does not give you the ability to check if an arbitrary check was thrown synchronously or asynchronously.

Note that precisely the same problems arise with  unsafeInterleaveIO . Conclusion: don’t use  System.IO.Unsafe – but you already knew that.

Further reading: a number of ghc bugs are related to this problem; see the discussion at 2558, 3997 and 5092 ; an old email thread on haskell-cafe, and the documentation of Control.Exception.

Brief Intro to Quasi-Quotation (Show me the types already)

This posts serves as a brief introduction to quasi-quotation in Haskell, because I couldn’t make much sense of the existing documentation, which gets bogged down in unnecessary details about writing parsers, the use of SYB, etc. Also, although quasi-quotation borrows syntax from Template Haskell, the TH expression  [|e|]  and the QQ  [qq|e|]  are false friends at best.

Recap: Template Haskell

Template Haskell is a library and language extension for writing Haskell meta programs: Haskell code that generates Haskell code (sometimes called macros in other language communities). The language extension allows us to quote Haskell expressions:

The quote syntax  [| someExpression |] is a convenient way to create quoted expressions; that is, values of type  Q Exp ; likewise,  [t| someType |]  can be used to quote types.  Q is the Template Haskell monad, which allows to create fresh variables, get location information, or even perform arbitrary IO;  Exp and  Type are types from the TH library that reify Haskell expressions and types. There’s nothing special about them; we could have written 

instead (the double tick indicates we want the name of the type, not the type itself).

We can use a quoted expression where Haskell expects an expression by splicing it; similarly for quoted types. For instance, we can write

Quasi-Quotation

Quasi-quotation extends Template Haskell and makes it possible to write custom parsers. The most important data type is

Here’s a trivial example:

But now here’s the confusing part: consider the following example

This is a splice, not a quote! The appropriate parser in the quasi quoter (depending on context) is used to convert the string to a quoted expression, and is then spliced in as an actual Haskell expression; in fact, this example is equivalent to

Really the only difference is that the syntax is somewhat more convenient, that it automatically picks the right parser for the context (type vs expression, etc.); moreover, quasi-quotes can be used in patterns, as we shall see below.

Meta-Variables and Anti-Quotation

First two more Template Haskell examples:

The first example uses simple type class defined in the TH libraries:

The second example shows that we can splice inside quotes; actually,  ex8 is an identify function (quoting and splicing are inverses). Unless we modify our quasi-quoter, however, the following two functions probably don’t have the intended effect (whatever the intended effect was):

Both of these functions ignore their argument; the first evaluates to the string "x"  and the second evaluates to the string "$x" . If we want to support meta-variables we need to modify the parsers for our quasi-quoter. The convention is that parsers in quasi-quoters recognize $x  as referring to a meta-variable x . We can define a quasi-quoter that only recognizes these as

and then define

(But note the difference in type between ex8  and ex9.) In fact, if we extend our quasi-quoter with a parser for patterns too:

then we can also use a quasi-quote in a pattern position (something that TH does not support):

Conclusions

If you are already familiar with Template Haskell then quasi-quotation isn’t much of an extension, except that the resemblance in syntax is confusing and misleading. The only thing I haven’t covered in this short post are  dataToExpQ  and  dataToPatQ , which are basically generic versions of TH’s  Lift class, with support for anti-quotation. See Section 3.2 of the original paper for details.

How to be a good coach

Over the years in my insane attempt to reach my Black Belt Instructor qualification in Krav Maga I have trained with a great many coaches in a great many countries. Some have been awesome; Gerwin Kranenburg (2nd dan) of Safety Training Center in the Netherlands and Matt Romond (3rd dan) of Krav Maga Worldwide in Los Angeles spring to mind; and, more recently but in a different field, John and Evelyn of Salsa Dublin are fantastic instructors. Other instructors have been terrible. But what exactly makes a good coach? Continue reading

Comprehensive Haskell Sandboxes

Serious Haskell developers will want to test their packages against different versions of ghc, different versions of libraries, etc. It is therefore useful to have multiple Hackage development environments, or sandboxes. A comprensive sandbox contains:

  1. An installation of ghc
  2. A package database
  3. cabal configuration (for instance, so that we can pin packages)

Moreover, good sandboxes are

  1. isolated from each other: only the active sandbox can be modified
  2. relocatable: it should be possible to copy the sandbox ~/env/ghc762 to ~/env/client1 to use as the basis for a new sandbox, or to copy the entire set of sandboxes (~/env) from one machine to another (suitably similar) machine (this means that paths in config files or baked into executables should never mention the name of the sandbox)
  3. self-contained: there should be no need for a system wide install of ghc
  4. transparent: we should be able to use the standard tools (ghc, cabal) as they are

There are existing tools for Haskell sandboxes (such as cabal-dev or hsenv), but none satisfy all of the above requirements (to the best of my knowledge). However, it is easy enough to set up our own.

Continue reading

Performance problems with -threaded?

Consider the following two implementations of a very simple ping/pong server and client, one written in C and one written in Haskell:

Neither of them has been particularly optimized, that’s not the point of this post. The point of this post will become evident when we measure the latency for the following three programs:

  1. The C program compiled with -O2
  2. The Haskell program compiled with -O2
  3. The Haskell program compiled with -O2 and -threaded

Continue reading