The Future of Haskell discussion at the Haskell Workshop
Dear Haskellers, This year's Haskell Workshop, held in Uppsala as a part of PLI, traditionally concluded with a discussion on the future of Haskell. This time an attempt was made to structure the discussion a little bit by focusing on two specific topics, and by having each topic being introduced by a short presentation. The first topic was Haskell records, introduced by Simon Peyton Jones, Microsoft Research, Cambridge, UK. The second topic was GUI libraries for Haskell, introduced by Axel Simon, the University of Kent, UK. While the current Haskell record system, or rather support for labeled fields, is vastly superior to not having any record facility at all, and appealing due to its simplicity and not incurring any run-time penalty, most people would agree that it does leave a lot be desired. However, they would not necessarily agree on exactly what is to be desired: the design space is quite large, and it is not easy to evaluate how useful various record features would be in practice, and if the cost in terms of increased language complexity and backwards compatibility issues is warranted. Unsurprisingly, opinions expressed during the discussion were rather divided. In the end, it seemed that the fact that the present system, despite its faults, is simple and has proved to be useful convinced a majority of the people present that if the system were to be improved, it should only be rather modest improvements that would not break backward compatibility. For example, one of the most annoying limitations of the present system is that record labels have to be distinct. Maybe this restriction could be lifted without sacrificing compatibility. Here is how Simon Peyton Jones summarized the discussion: The conclusion I took away was this There are undoubted advantages to having better records, but (a) they all make the language more complicated (b) there are many possible design choices (not only has/lacks, but also record concatenation, length vs depth subtyping, and more I'm sure) (c) they almost certainly conflict with existing programs (d) the existing system is really not too bad That all argues for the status quo. I did have a conversation with Peter Thiemann afterwards. We discussed a record system which is an upward compatible extension of what we have now, though less powerful than the variants I have previously proposed. * Records are not anonymous. e.g. {x::Int, y::Bool} is not a type They are declared exactly as now, so that data T = T { x::Int, y::Bool } declares a type T. * However, you can have more than one record with the same field name. So the field selectors are overloaded, much as with has-predicates x :: (t has x::a) => t -> a * So a function like f v = v.x + v.y would get the inferred type f :: (t has x::a, t has y::a, Num a) => t -> a * Also retain Haskell's existing record construction and update syntax could be possible. The GUI library discussion focused on questions such as what exactly are the desirable properties of such a library. For example, to what extent is it necessary that applications are able to adopt the look-and-feel of the platform on which they happen to be running. Related to this was the question of whether to focus efforts on a Common GUI API (CGA) that would allow applications to adapt to specific platforms, or whether it would be sufficient to go for something based on an existing cross-platform API, such as wxWindows, even if that meant violating certain look-and-feel aspects on certain platforms, and inability to access platform-specific functionality. Axel Simon has promised to e-mail a more complete record of the GUI-part of the discussion shortly. All the best, /Henrik -- Henrik Nilsson Yale University Department of Computer Science nilsson@cs.yale.edu
On Tuesday 09 September 2003 01:57, nilsson@cs.yale.edu wrote:
Here is how Simon Peyton Jones summarized the discussion:
The conclusion I took away was this
There are undoubted advantages to having better records, but
(a) they all make the language more complicated
(b) there are many possible design choices (not only has/lacks, but also record concatenation, length vs depth subtyping, and more I'm sure)
(c) they almost certainly conflict with existing programs
(d) the existing system is really not too bad
I rarely use named fields in my Haskell progs with Haskell as it is for 2 reasons.. 1- The field names must be unique 2- In ghc at least, you can't mix field names with existential quantification (well you couldn't last time I tried it:-)
That all argues for the status quo.
IMHO preserving the status quo wrt records should be low priority. It really doesn't bother me much if new (useful) language features break existing code. I think this is a better option than permanently impoverishing the language and/or forcing users to migrate their entire code to some other less impoverished language which may appear in the future. What I don't particularly want to see is some "half baked" record system, the usefulness of which has been compromised by the need to retain backwards compatibility. I quite liked what I saw of the "First Class Modules" paper. Is there some reason why we can't have (shouldn't have?) that. (Apart from the additional workload it places on Haskell implementors :-) Regards -- Adrian Hey
On Tue, 9 Sep 2003, Adrian Hey wrote:
I rarely use named fields in my Haskell progs with Haskell as it is ...
but you sure agree records are useful for collecting heterogenous data? for example, see data DynFlags here: http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/main/CmdLineO...
IMHO preserving the status quo wrt records should be low priority. It really doesn't bother me much if new (useful) language features break existing code.
but this might be an issue for others, who have to maintain "legacy" code. best regards, -- -- Johannes Waldmann ---- http://www.informatik.uni-leipzig.de/~joe/ -- -- joe@informatik.uni-leipzig.de -- phone/fax (+49) 341 9732 204/209 -- .. .. Viertes Leipziger Jongliertreffen, 17. - 19. Oktober 2003 .. .. .. .. http://www.informatik.uni-leipzig.de/~joe/juggling/vier/ .. ..
Hello, I may be wrong but can't we keep old records and add new ones (as proposed in the First Class Modules paper) with a different syntax? Ussual records and extensible records are both usefull, in different cases. Best regards, Nicolas Oury Le mardi, 9 sep 2003, à 14:52 Europe/Paris, Johannes Waldmann a écrit :
On Tue, 9 Sep 2003, Adrian Hey wrote:
I rarely use named fields in my Haskell progs with Haskell as it is ...
but you sure agree records are useful for collecting heterogenous data? for example, see data DynFlags here:
http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/main/ CmdLineOpts.lhs
IMHO preserving the status quo wrt records should be low priority. It really doesn't bother me much if new (useful) language features break existing code.
but this might be an issue for others, who have to maintain "legacy" code.
best regards, -- -- Johannes Waldmann ---- http://www.informatik.uni-leipzig.de/~joe/ -- -- joe@informatik.uni-leipzig.de -- phone/fax (+49) 341 9732 204/209 --
.. .. Viertes Leipziger Jongliertreffen, 17. - 19. Oktober 2003 .. .. .. .. http://www.informatik.uni-leipzig.de/~joe/juggling/vier/ .. ..
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
On Tuesday 09 September 2003 13:52, Johannes Waldmann wrote:
On Tue, 9 Sep 2003, Adrian Hey wrote:
I rarely use named fields in my Haskell progs with Haskell as it is ...
but you sure agree records are useful for collecting heterogenous data?
Yes, I would agree that even the current situation is sometimes better than having a large number of unnamed fields (as a huge-tuple say). But for the average product type or constructor (2..3 fields), it just isn't worth the aggrovation IMO. Regards -- Adrian Hey
G'day all. On Tue, Sep 09, 2003 at 02:52:48PM +0200, Johannes Waldmann wrote:
but this might be an issue for others, who have to maintain "legacy" code.
You know a language has made it when we're talking about "legacy" code. On the other hand, you have to worry about a pure declarative language where support for anything "legacy" is a priority. Just a little bit. Cheers, Andrew Bromage
On Wednesday 10 September 2003 04:54, Andrew J Bromage wrote:
G'day all.
On Tue, Sep 09, 2003 at 02:52:48PM +0200, Johannes Waldmann wrote:
but this might be an issue for others, who have to maintain "legacy" code.
You know a language has made it when we're talking about "legacy" code.
On the other hand, you have to worry about a pure declarative language where support for anything "legacy" is a priority. Just a little bit.
On reflection, I can think of one group of Haskellers who might get a bit upset by such changes. If I'd written (or purchased) a text book which was now full of obsoleted code examples I wouldn't be very happy. But I guess it would be possible to do something too suit users of "old" and "new" Haskell with suitably chosen pragmas or compiler switches without too much difficulty. Regards -- Adrian Hey
hello, i think records are very useful, and we don't use them much in haskell, becuase the current record system is not very good. Adrian Hey wrote:
IMHO preserving the status quo wrt records should be low priority. It really doesn't bother me much if new (useful) language features break existing code. I think this is a better option than permanently impoverishing the language and/or forcing users to migrate their entire code to some other less impoverished language which may appear in the future. i also think that having backwards compatability is not much of an issue. after all, ghc has introduces a number of not backward compatable changes to haskell, and i never heard any complaints. i am referring to the hirarchical modules, and more recently template haskell, which has introduced a number of syntactic differences, and we had to actually go through our code and fix it to work with ghc 6.
What I don't particularly want to see is some "half baked" record system, the usefulness of which has been compromised by the need to retain backwards compatibility. I quite liked what I saw of the "First Class Modules" paper. Is there some reason why we can't have (shouldn't have?) that. (Apart from the additional workload it places on Haskell implementors :-) there has been a lot of work on record systems, so there really is no excuse for having a half-baked recrod system. the trex implementation in hugs tried to retain backward compatability with haskell, which resulted in a rather ugly syntax (this of course is just my opinion :-)
my preference would be to have something simillar to trex but with a nicer syntax, i.e. extensible records that do not need to be declared. incidently i gathered that people wanted reocrds that support record concatenation, does anyone have any examples of what that might be used for? bye iavor -- ================================================== | Iavor S. Diatchki, Ph.D. student | | Department of Computer Science and Engineering | | School of OGI at OHSU | | http://www.cse.ogi.edu/~diatchki | ==================================================
Hi. Here's another opinion for the "Records! Records!" chorus: - The record and module system is one of the two big things I'd like to see changed in Haskell. (OT: the other is subtyping.) - It shouldn't happen before Haskell 2, because of backward compatability. (The dot operator for function composition is widely used, but is the obvious choice for record projection.) - The way to get a feature into Haskell 2 begins with contributing it as an optional extension to GHC and/or nhc98 and/or Hugs. - I'd like something similar to Cayenne's record system, which combines records, modules and let-expressions. But with these refinements: * Dot notation for record opening. Instead of Cayenne's open rec_expr in expr allow (rec_expr).(expr) which has the familiar single-field projection as a special case (rec_expr).field_name * Some sort of catenation or merge facility. Speaking of which... Iavor Diatchki writes: : | incidently i gathered that people wanted reocrds that support record | concatenation, does anyone have any examples of what that might be used for? When a module imports and reexports some other modules, it is effectively doing record catenation. (It may add a few fields of its own, if it exports any declarations, but that can be handled by record extension as opposed to catenation.) The (relational database) join operator also needs it - if you're into doing such things in Haskell. I've implemented a language with a record system along the lines I've just described. It's part of my work, but the record system isn't commercially sensitive. If it pans out well, I'll look into contributing it to a Haskell implementation. (O'Hugs may well be the best fit.) - Tom
Iavor Diatchki <diatchki@cse.ogi.edu> writes:
Adrian Hey wrote:
IMHO preserving the status quo wrt records should be low priority. It really doesn't bother me much if new (useful) language features break existing code. I think this is a better option than permanently impoverishing the language and/or forcing users to migrate their entire code to some other less impoverished language which may appear in the future.
I also think that having backwards compatability is not much of an issue. After all, ghc has introduces a number of not backward compatable changes to haskell, and I never heard any complaints.
Oh no? Implicit parameters: I'm sure it is a great thing, but I'd already used the (?) operator, and need -fglasgow-exts. Now my program depends on a bunch of well places spaces to compile. Template Haskell: really cool new feature, which just happens to use a syntax that overlaps with the list comprehension syntax. And now, let's just screw any backwards compatibility, and re-engineer the records system¹. I don't need any of this, and it makes my life harder. Are you guys going to keep at it, until I regret ever using Haskell? There was recently a thread about using Haskell for something else than Haskell compilers; well, if you actually want people to do this, then you can't constantly keep changing the language. -kzm PS: For the record, I think the compiler developers are in general doing a great job of augmenting the language *without sacrificing backwards compatibility*. But compatibility is important. Branch GHC and develop a new language instead! -- If I haven't seen further, it is by standing in the footprints of giants
What about "ad-hoc overloading" (allowing visible entities to share names, as long as they can be distinugished by their typing). This is orthogonal to the "proper records" issue (?) but it might improve the current situtation (?) and it seems backward-compatible (?) Of course this would need an extension of the type checker (but not in the interface files, since this kind of overloading should only happen when using an name, not when defining it). -- -- Johannes Waldmann ---- http://www.informatik.uni-leipzig.de/~joe/ -- -- joe@informatik.uni-leipzig.de -- phone/fax (+49) 341 9732 204/209 -- .. .. Viertes Leipziger Jongliertreffen, 17. - 19. Oktober 2003 .. .. .. .. http://www.informatik.uni-leipzig.de/~joe/juggling/vier/ .. ..
Johannes Waldmann <joe@informatik.uni-leipzig.de> writes:
What about "ad-hoc overloading" (allowing visible entities to share names, as long as they can be distinugished by their typing).
This is orthogonal to the "proper records" issue (?) but it might improve the current situtation (?) and it seems backward-compatible (?)
Yes. Don't get me wrong; please go and define "proper records", improve the record system accordingly, adapt and implement. I just wanted to correct the impression that there were no complaints about broken backwards compatibility. Because it is - or at least, it can be - a real problem. Sometimes it has to be done in order to set things right, but it shouldn't be done lightly. There is also the issue of weighing down the language with features and extensions. It may give you more expressive power, but it also makes the language harder to master, and programs more difficult to maintain.
Of course this would need an extension of the type checker
Doesn't worry me overly, it is Somebody Else's Problem :-) -kzm -- If I haven't seen further, it is by standing in the footprints of giants
On Wednesday 10 September 2003 10:51, Ketil Z. Malde wrote:
And now, let's just screw any backwards compatibility, and re-engineer the records system¹.
I don't need any of this, and it makes my life harder. Are you guys going to keep at it, until I regret ever using Haskell?
I can't speak for any Haskell implementors or whether or not they intend to keep going at it. But maybe there are people who will regret ever using Haskell if nothing is done about the current records/modules situation (me for one). I don't mind waiting a while, if it's still unclear what should be done or can reasonably done given current state of the art re. the necessary type theory. But my understanding of the original summary was that I might as well give up hope of ever seeing anything like this in Haskell, for fear of upsetting the status quo. I don't like that idea much. I think if you want to use a language which is close to state of the art you have to accept some change. Better this than see it permanently crippled by backwards compatibility constraints. That said, I don't see why any backwards compatibility problems can't be managed with suitable compiler switches or whatever, which seems to be what Simon.M. is proposing for ghc. Regards -- Adrian Hey
I'd like to add a voice of dissent here. I would much prefer it if Haskell didn't add specific extensible records support - even if it could be done without breaking backwards compatibility. This is because I believe that extensible records encourage poor style. They encourage people to expose the internal representation of their structures, allowing users to match on internal fields rather than using accessor functions. One of the things that I like about the current Haskell record system is the fact that record selectors are functions. This means that, if I change the structure of a type, I can just replace the record selector with a normal function. On a similar line of argument, one change that I think would be nice would be for record updaters to also be functions. Then the following code x {name1 = bla, name2 = blob} would translate to the following: set_name1 bla $ set_name2 blob $ x This would allow record updates to be overridden in the same way that record selectors can be. Perhaps the best way to get the record extensibility features that people seem to want would be to allow record selectors (and updaters) to be in type classes, just like other functions. So in summary, here is my proposal: No specific "extensible records" system. Define record update to be a function just like record selection is. Allow these functions to be in type classes. -Rob
Hi!
So in summary, here is my proposal:
No specific "extensible records" system.
Define record update to be a function just like record selection is.
Allow these functions to be in type classes.
I do not understand the second and third point: As I understand your idea, record selectors and updaters should still be defined by the datatype declaration. What does it then mean that they be "allowed" to be defined in type classes? Would that happen automatically? Cheers, /kff
Hi!
So in summary, here is my proposal:
No specific "extensible records" system.
Define record update to be a function just like record selection is.
Allow these functions to be in type classes.
I do not understand the second and third point: As I understand your idea, record selectors and updaters should still be defined by the datatype declaration. What does it then mean that they be "allowed" to be defined in type classes? Would that happen automatically?
I was thinking of something along the following lines: class Wibble a where wibble :: a -> Int wobble :: a -> String set_wibble :: Int -> a -> a set_wobble :: String -> a -> a data Foo = Foo {wibble :: Int, wobble :: String} deriving Wibble The Wibble class defines selector and updater functions for fields called wibble and wobble. When I define the datatype Foo, I give it fields called wibble and wobble, which will define the functions in Wibble. If I say "deriving Wibble" then the type system acknowledges that these functions are implementing the class Wibble. If I had not derived Wibble then there would have been a name clash. We could imagine the definition of Foo being automatically desugared to the following: data Foo = Foo Int String instance Wibble Foo where wibble (x,_) = x wobbble (_,y) = y set_wibble x (_,y) = (x,y) set_wobble y (x,_) = (x,y) Note that Wibble is a normal class. I could thus implement Wibble in a class that was not a record. For example, the following, rather dull, implementation: instance Wibble () where wibble () = 3 wobble () = "hello" set_wibble _ _ = () set_wobble _ _ = () Does that make things clearer? -Rob
Yes, things are clearer and I rather like the idea. The only thorny issue is that the update function for field 'wibble' is formed from but not equal to the field name itself. In short, the magic thing would be in the 'deriving' clause: If the data type declares fields with names x_1, ..., x_n and the class mentioned declares operators y_1, ..., y_k and set_y_1, ..., set_y_k where {y_1, ..., y_k} is a subset of {x_1, ..., x_k}, of the appropriate types, then the corresponding instance declarations are generated. Cheers, /kff
Yes, things are clearer and I rather like the idea. The only thorny issue is that the update function for field 'wibble' is formed from but not equal to the field name itself.
In short, the magic thing would be in the 'deriving' clause:
If the data type declares fields with names x_1, ..., x_n and the class mentioned declares operators y_1, ..., y_k and set_y_1, ..., set_y_k where {y_1, ..., y_k} is a subset of {x_1, ..., x_k}, of the appropriate types, then the corresponding instance declarations are generated.
Yep. It would also be possible for a class to declare only the selector or only the updater for a field. E.g.: class FooGet a where foo :: a -> Int class FooSet a where set_foo :: Int -> a -> a data Bar = Bar {foo :: Int} deriving (FooGet, FooSet) -Rob
Karl-Filip Faxen wrote: | Yes, things are clearer and I rather like the idea. | The only thorny issue is that the update function for | field 'wibble' is formed from but not equal to the | field name itself. This could be solved by having an abstract type Field thusly (*): type Field r a set :: r -> Field r a -> a -> r get :: r -> Field r a -> a The example would then look like: class Wibble r where wibble :: Field r Int wobble :: Field r String data Foo = MkFoo{ wibble :: Int , wobble :: String } deriving Wibble What do you think of this? The type Field can be implemented as: data Field r a = MkField (r -> a -> r) (r -> a) set rec (MkField f _) x = f rec x get rec (MkField _ g) = g rec Regards, /Koen ---- (*) I prefer the following operators but I realize that there are other people who are less fond of binary operator symbols :-) type Field r a type Setting r (=:) :: Field r a -> a -> Setting r (!) :: r -> Setting r -> r (?) :: r -> Field r a -> a Such that selecting the field wibble from a record rec would look like: rec ? wibble And setting the field wibble from the record rec to the value val would look like: rec ! wibble =: val The last should parse as: rec ! (wibble =: val) /K
Karl-Filip Faxen wrote:
| Yes, things are clearer and I rather like the idea. | The only thorny issue is that the update function for | field 'wibble' is formed from but not equal to the | field name itself.
This could be solved by having an abstract type Field thusly (*):
[snip] All very cute :-)) The downside is of course that it would no longer be a compatible extension to the existing Haskell language. Current Haskell programs consider the field name to be a function from types to field values. If we are to retain compatibility then we need to preserve this. Still very cute though :-) [snip] -Rob
On Wed, 10 Sep 2003 10:26:04 +0100, Robert Ennals <Robert.Ennals@cl.cam.ac.uk> wrote:
class Wibble a where wibble :: a -> Int wobble :: a -> String set_wibble :: Int -> a -> a set_wobble :: String -> a -> a
data Foo = Foo {wibble :: Int, wobble :: String} deriving Wibble
The Wibble class defines selector and updater functions for fields called wibble and wobble.
When I define the datatype Foo, I give it fields called wibble and wobble, which will define the functions in Wibble. If I say "deriving Wibble" then the type system acknowledges that these functions are implementing the class Wibble. If I had not derived Wibble then there would have been a name clash.
What would you do if Wibble had more functions than just those 4? You'd need somewhere to put the implementations of the other functions for Foo. Ganesh
On Wed, 10 Sep 2003 10:26:04 +0100, Robert Ennals <Robert.Ennals@cl.cam.ac.uk> wrote:
class Wibble a where wibble :: a -> Int wobble :: a -> String set_wibble :: Int -> a -> a set_wobble :: String -> a -> a
data Foo = Foo {wibble :: Int, wobble :: String} deriving Wibble
The Wibble class defines selector and updater functions for fields called wibble and wobble.
When I define the datatype Foo, I give it fields called wibble and wobble, which will define the functions in Wibble. If I say "deriving Wibble" then the type system acknowledges that these functions are implementing the class Wibble. If I had not derived Wibble then there would have been a name clash.
What would you do if Wibble had more functions than just those 4? You'd need somewhere to put the implementations of the other functions for Foo.
I guess there are three options. A: Don't allow records to be instances of such classes. B: Add extra syntax to allow this. E.g something like this: data Foo = Foo {wibble :: Int} deriving Wibble where wobble x = "hello" set_wobble w x = x C: Declare instances using normal instance declarations: e.g. data Foo = Foo {wibble :: Int} instance Wibble Foo where wobble = x "hello" set_wobble w x = x -- wibble and set_wibble done automatically. This has the weakness that the compiler has to see the instance declaration when compiling the type declaration for Foo in order to know that the names are not clashing. It is however possibly the best option. -Rob
Robert Ennals <Robert.Ennals@cl.cam.ac.uk> writes: [Heavy snippage, hopefully preserving semantics]
data Foo = Foo {wibble :: Int, wobble :: String} deriving Wibble
We could imagine the definition of Foo being automatically desugared to the following:
data Foo = Foo Int String
instance Wibble Foo where wibble (x,_) = x wobbble (_,y) = y set_wibble x (_,y) = (x,y) set_wobble y (x,_) = (x,y)
Shouldn't that rather be: class HasWibble a where wibble :: a -> Int set_wibble :: a -> Int -> a class HasWobble a where ... data Foo = Foo Int String instance HasWibble Foo where wibble (Foo x _) = x set_wibble (Foo x y) z = Foo z y instance HasWobble Fo where... In order to let another record provide just a 'wibble' without a 'wobble'? One danger of such an approach (implicit classes and instances) might be non-intuitive error messages. -kzm -- If I haven't seen further, it is by standing in the footprints of giants
On Wed, Sep 10, 2003 at 02:27:33PM +0200, Ketil Z. Malde wrote:
Shouldn't that rather be:
class HasWibble a where wibble :: a -> Int set_wibble :: a -> Int -> a
class HasWobble a where ...
Or even: class HasWibble a b | a -> b where wibble :: a -> b set_wibble :: a -> b -> a class HasWobble a b | a -> b where ... Best regards, Tom -- .signature: Too many levels of symbolic links
On Wed, Sep 10, 2003 at 02:27:33PM +0200, Ketil Z. Malde wrote:
Shouldn't that rather be:
class HasWibble a where wibble :: a -> Int set_wibble :: a -> Int -> a
class HasWobble a where ...
Or even:
class HasWibble a b | a -> b where wibble :: a -> b set_wibble :: a -> b -> a
class HasWobble a b | a -> b where ...
It can be. The programmer can declare the type classes however they like. It is important to note that type classes are NOT automatically generated in my proposal. The type classes I describe are bog standard normal type classes. The only magic takes place when records are made instances of type classes, at which point the fields are translated into default instances. -Rob
ketil@ii.uib.no (Ketil Z. Malde) writes:
Robert Ennals <Robert.Ennals@cl.cam.ac.uk> writes:
BTW, isn't this more or less exactly what Simon suggested (at the very top of this thread)?
Not really, no. I assume you mean the system suggested by Peter Thieman, outlined in the initial email by Henrik Nilsson. My system has the following differences: Record updaters become normal functions. (and recold selectors remain functions) Normal type classes are used to implement them. (no magic "has" constraints) Type classes are not magically inferred. They are manually declared just like any other type class would be. As I interpret it, the system proposed at the top of the thread treats record fields as something special, and I am very keen that this should not happen. I think that it is important that one should be able to replace a record field with accessor functions. -Rob
participants (13)
-
Adrian Hey -
Andrew J Bromage -
Ganesh Sittampalam -
Iavor Diatchki -
Johannes Waldmann -
Karl-Filip Faxen -
ketil@ii.uib.no -
Koen Claessen -
Nicolas Oury -
nilsson@cs.yale.edu -
Robert Ennals -
Tom Pledger -
Tomasz Zielonka