Archive for the 'Programming' Category

Did you to have be so blunt?

Tuesday, September 23rd, 2008

http://realtimecollisiondetection.net/blog/?p=81

My favourites:

In contrast, design patterns are purported “master programmer advice” strongly suggesting to young or otherwise impressionable programmers that the design patterns convey important concepts, practices, or principles that have been “prethought.” However, design patterns are not “master programmer advice!”

Far from “master programmers,” design patterns are the work of people who do conferences, talks, and books for a living, to further their own cause

And the clincher:

Design patterns are spoonfeed material for brainless programmers incapable of independent thought, who will be resolved to producing code as mediocre as the design patterns they use to create it.

I’m sure you knew you’d be standing on toes, despite the the overwhelmingly defensible truth value of your statements. Don’t adjust your sight Christer, it’s dead on target ;)

Partially Applying Scala type variables

Monday, September 22nd, 2008

Below is a neat trick that others may find useful when designing APIs using the Scala programming language.

Scala’s type inferencer is not as clever as some. As a result, we often find ourselves explicitly annotating type variables in certain contexts. This can become a little annoying, but what is worse, is if you have a type variable list and only one of those requires explicit specification, the others must also be explicitly specified even though they would have otherwise been inferred.

Let me demonstrate. I will use Scala’s higher-kinds, which are never inferred (this is quite acceptable given the problems associated with inferring higher-kinds — consider Java and C# where they do not even exist, thus leading to an enormous repetitive chore) though other examples may be applicable. However, it can be annoying if you were to write say, the Monad join function:

def join[M[_], A](m: M[M[A]]): M[A] = error("todo")

A caller invocation might look like:

val x = join[List, Int](List(List(1, 2, 3), List(4, 5, 6)))

Notice the explicit annotation with the List type constructor, however, the second type variable (Int) must also be explicitly specified, even though it could have otherwise been inferred. This is a bit annoying.

We can do away with it like so:

def join[M[_]] = new {
  def apply[A](m: M[M[A]]): M[A] = error("todo")
}

And now the caller code no longer has that clumsy type annotation:

val x = join[List](List(List(1, 2, 3), List(4, 5, 6)))

Yay! Have a nice day :)

20 Intermediate Haskell Exercises

Thursday, September 18th, 2008
class Fluffy f where
  furry :: (a -> b) -> f a -> f b
 
-- Exercise 1
-- Relative Difficulty: 1
instance Fluffy [] where
  furry = error "todo"
 
-- Exercise 2
-- Relative Difficulty: 1
instance Fluffy Maybe where
  furry = error "todo"
 
-- Exercise 3
-- Relative Difficulty: 5
instance Fluffy ((->) t) where
  furry = error "todo"
 
newtype EitherLeft b a = EitherLeft (Either a b)
newtype EitherRight a b = EitherRight (Either a b)
 
-- Exercise 4
-- Relative Difficulty: 5
instance Fluffy (EitherLeft t) where
  furry = error "todo"
 
-- Exercise 5
-- Relative Difficulty: 5
instance Fluffy (EitherRight t) where
  furry = error "todo"
 
class Misty m where
  banana :: (a -> m b) -> m a -> m b
  unicorn :: a -> m a
  -- Exercise 6
  -- Relative Difficulty: 3
  -- (use banana and/or unicorn)
  furry' :: (a -> b) -> m a -> m b
  furry' = error "todo"
 
-- Exercise 7
-- Relative Difficulty: 2
instance Misty [] where
  banana = error "todo"
  unicorn = error "todo"
 
-- Exercise 8
-- Relative Difficulty: 2
instance Misty Maybe where
  banana = error "todo"
  unicorn = error "todo"
 
-- Exercise 9
-- Relative Difficulty: 6
instance Misty ((->) t) where
  banana = error "todo"
  unicorn = error "todo"
 
-- Exercise 10
-- Relative Difficulty: 6
instance Misty (EitherLeft t) where
  banana = error "todo"
  unicorn = error "todo"
 
-- Exercise 11
-- Relative Difficulty: 6
instance Misty (EitherRight t) where
  banana = error "todo"
  unicorn = error "todo"
 
-- Exercise 12
-- Relative Difficulty: 3
jellybean :: (Misty m) => m (m a) -> m a
jellybean = error "todo"
 
-- Exercise 13
-- Relative Difficulty: 6
apple :: (Misty m) => m a -> m (a -> b) -> m b
apple = error "todo"
 
-- Exercise 14
-- Relative Difficulty: 6
moppy :: (Misty m) => [a] -> (a -> m b) -> m [b]
moppy = error "todo"
 
-- Exercise 15
-- Relative Difficulty: 6
-- (bonus: use moppy)
sausage :: (Misty m) => [m a] -> m [a]
sausage = error "todo"
 
-- Exercise 16
-- Relative Difficulty: 6
-- (bonus: use apple + furry')
banana2 :: (Misty m) => (a -> b -> c) -> m a -> m b -> m c
banana2 = error "todo"
 
-- Exercise 17
-- Relative Difficulty: 6
-- (bonus: use apple + banana2)
banana3 :: (Misty m) => (a -> b -> c -> d) -> m a -> m b -> m c -> m d
banana3 = error "todo"
 
-- Exercise 18
-- Relative Difficulty: 6
-- (bonus: use apple + banana3)
banana4 :: (Misty m) => (a -> b -> c -> d -> e) -> m a -> m b -> m c -> m d -> m e
banana4 = error "todo"
 
newtype State s a = State {
  state :: (s -> (s, a))
}
 
-- Exercise 19
-- Relative Difficulty: 9
instance Fluffy (State s) where
  furry = error "todo"
 
-- Exercise 20
-- Relative Difficulty: 10
instance Misty (State s) where
  banana = error "todo"
  unicorn = error "todo"

20 Intermediate Scala Exercises

Wednesday, September 10th, 2008

I will be publishing answers to these exercises as well as the Revised Scala Exercises in the near future. In the meantime, see if you can tackle the exercises below. In almost all cases, the type signature is enough to derive what the implementation should be. In all other cases, the solution is as difficult to derive anyway, so consider it an equivalent achievement.

The source file below compiles, but is missing certain function implementations (where you see error("todo")). Enjoy and if you have questions, please feel free to post them :)

trait PartialType[T[_, _], A] {
  type Apply[B] = T[A, B]
  type Flip[B] = T[B, A]
}
 
trait Fluffy[F[_]] {
  def furry[A, B](f: A => B, fa: F[A]): F[B]
}
 
object Fluffy {
  // Exercise 1
  // Relative Difficulty: 1
  def ListFluffy: Fluffy[List] = error("todo")
 
  // Exercise 2
  // Relative Difficulty: 1
  def OptionFluffy: Fluffy[Option] = error("todo")
 
  // Exercise 3
  // Relative Difficulty: 1
  def StreamFluffy: Fluffy[Stream] = error("todo")
 
  // Exercise 4
  // Relative Difficulty: 1
  def ArrayFluffy: Fluffy[Array] = error("todo")
 
  // Exercise 5
  // Relative Difficulty: 5
  def Function1Fluffy[X]: Fluffy[PartialType[Function1, X]#Apply] =
    error("todo")
 
  // Exercise 6
  // Relative Difficulty: 6
  def EitherLeftFluffy[X]: Fluffy[PartialType[Either.LeftProjection, X]#Flip] =
    error("todo")
 
  // Exercise 7
  // Relative Difficulty: 4
  def EitherRightFluffy[X]: Fluffy[PartialType[Either.RightProjection, X]#Apply] =
    error("todo")
}
 
trait Misty[M[_]] extends Fluffy[M] {
  def banana[A, B](f: A => M[B], ma: M[A]): M[B]
 
  def unicorn[A](a: A): M[A]
 
  // Exercise 8
  // Relative Difficulty: 3
  // (use banana and/or unicorn)
  def furry[A, B](f: A => B, ma: M[A]) = error("todo")
}
 
object Misty {
  // Exercise 9
  // Relative Difficulty: 2
  def ListMisty: Misty[List] = error("todo")
 
  // Exercise 10
  // Relative Difficulty: 2
  def OptionMisty: Misty[Option] = error("todo")
 
  // Exercise 11
  // Relative Difficulty: 2
  def StreamMisty: Misty[Stream] = error("todo")
 
  // Exercise 12
  // Relative Difficulty: 2
  def ArrayMisty: Misty[Array] = error("todo")
 
  // Exercise 13
  // Relative Difficulty: 6
  def Function1Misty[X]: Misty[PartialType[Function1, X]#Apply] =
    error("todo")
 
  // Exercise 14
  // Relative Difficulty: 7
  def EitherLeftMisty[X]: Misty[PartialType[Either.LeftProjection, X]#Flip] =
    error("todo")
 
  // Exercise 15
  // Relative Difficulty: 5
  def EitherRightMisty[X]: Misty[PartialType[Either.RightProjection, X]#Apply] =
    error("todo")
 
  // Exercise 16
  // Relative Difficulty: 3
  def jellybean[M[_], A](ma: M[M[A]], m: Misty[M]): M[A] = error("todo")
 
  // Exercise 17
  // Relative Difficulty: 6
  def apple[M[_], A, B](ma: M[A], mf: M[A => B], m: Misty[M]): M[B] =
    error("todo")
 
  // Exercise 18
  // Relative Difficulty: 6
  def moppy[M[_], A, B](as: List[A], f: A => M[B], m: Misty[M]): M[List[B]] =
    error("todo")
}
 
object AdvancedFun {
  case class State[S, A](f: S => (S, A))
 
  // Exercise 19
  // Relative Difficulty: 9
  def StateFluffy[S]: Fluffy[PartialType[State, S]#Apply] = error("todo")
 
  // Exercise 20
  // Relative Difficulty: 10
  def StateMisty[S]: Misty[PartialType[State, S]#Apply] = error("todo")
}

Haskell > Scala > (Java 7 <=> Functional Java) > Java

Friday, September 5th, 2008

Write a parser that accepts command line arguments.
For each command line argument, print out true or false,
depending on whether or not that value parses.

For a value to parse, it must consist entirely of these
characters: '(', ')', '[', ']‘. Any other character renders
the parse invalid and so prints “false”.

The value must also be “balanced”. That is, for each opening
parenthesis or bracket, it is matched by a closing parenthesis
or bracket accordingly. The different bracket types must not
intersperse.

Here are some examples of successfully parsing values that
result in printing “true”:

""
"()"
"[]"
"([])"
"[()]"
"[]()"
"[][[([])]]"

Here are some examples of values that fail the parsing and
result in printing “false”:

"("
")"
"["
"]"
"]["
")("
"( )"
"([)"
"[)]"
"([)]"
"({})"
"[())]"

Using Haskell (without Parsec):

import Prelude hiding (foldr, any)
import Control.Monad
import Data.Foldable
import System
 
tokens = [('(', ')'), ('[', ']')]
 
parse x = any null (foldr (\c f -> (\s -> (const (c:s)) `fmap`
            flip lookup ((uncurry (flip (,))) `fmap` tokens)  c `mplus`
              (flip lookup tokens c >>= (\v ->
                do h:t <- return s
                   guard (v == h)
                   return t))) =<< f) (return []) x)
 
main = getArgs >>= print . (parse `fmap`)

Using Scala (without scala.util.parsing):

object Parser {
  val tokens = List(('(', ')'), ('[', ']'))
 
  def parse(s: String) =
    s.foldRight[Option[String]](Some(""))((a, b) => b flatMap
      (ss => {
        val s = ss.toList
        (lookup(tokens map { case (x, y) => (y, x) }, a)
          map (t => (a::s)) orElse
        (lookup(tokens, a) flatMap (v => s match {
          case Nil => None
          case h :: t => if(v == h) Some(t) else None
        }))) map (_.mkString)
      })) exists (_.isEmpty)
 
  def main(args: Array[String]) {
    args foreach (parse _ andThen println)
  }
 
  // The Scala API needs hand-holding
  def lookup[A, B](x: List[(A, B)], a: A) =
    x.find { case (aa, _) => a == aa } map (_._2)
}

Using Java 1.5 and Functional Java:

import fj.F;
import fj.F2;
import fj.Function;
import static fj.P.p;
import fj.P1;
import fj.P2;
import fj.data.List;
import static fj.data.List.asString;
import static fj.data.List.fromString;
import static fj.data.List.list;
import static fj.data.List.lookup;
import fj.data.Option;
import static fj.data.Option.some;
import static fj.function.Strings.isEmpty;
import static fj.pre.Equal.charEqual;
import static fj.pre.Show.booleanShow;
 
final class Parser {
  @SuppressWarnings("unchecked")
  static final List<P2<Character, Character>> tokens =
    list(p('(', ')'), p('[', ']'));
 
  static boolean parse(final String s) {
    return fromString(s).foldRight(
      new F2<Character, Option<String>, Option<String>>() {
      public Option<String> f(final Character c, final Option<String> b) {
        return b.bind(new F<String, Option<String>>() {
          public Option<String> f(String s) {
            final List<Character> ss = fromString(s);
            return lookup(charEqual,
              tokens.map(P2.<Character, Character>swap_()), c)
                .map(Function.<Character,
                  List<Character>>constant(ss.cons(c)))
                .orElse(lookup(charEqual, tokens, c)
                .bind(new F<Character, Option<List<Character>>>() {
                  public Option<List<Character>> f(final Character v) {
                    return ss.isEmpty() || v != ss.head() ?
                        Option.<List<Character>>none() :
                        some(ss.tail());
                  }
                })).map(asString());
          }
        });
      }
    }, some("")).exists(isEmpty);
  }
 
  public static void main(final String[] args) {
    for(final String s : args) {
      booleanShow.println(parse(s));
    }
  }
}

Using Java BGGA and Functional Java:

import fj.Function;
import static fj.P.p;
import fj.P1;
import fj.P2;
import fj.data.List;
import static fj.data.List.asString;
import static fj.data.List.fromString;
import static fj.data.List.list;
import static fj.data.List.lookup;
import fj.data.Option;
import static fj.data.Option.some;
import static fj.function.Strings.isEmpty;
import static fj.pre.Equal.charEqual;
import static fj.pre.Show.booleanShow;
 
final class ParserBGGA {
  @SuppressWarnings("unchecked")
  static final List<P2<Character, Character>> tokens =
    list(p('(', ')'), p('[', ']'));
 
  static boolean parse(final String s) {
    return fromString(s).foldRight({ char c, Option<String> b =>
      b.bind({ String ss =>
        final List<Character> s = fromString(ss);
          lookup(charEqual,
            tokens.map(P2.<Character, Character>swap_()), c)
          .map(Function.<Character, List<Character>>constant(s.cons(c)))
          .orElse(lookup(charEqual, tokens, c)
          .bind({ char v =>
            s.isEmpty() || v != s.head() ?
              Option.<List<Character>>none() :
              some(s.tail())})).map(asString())})}
      , some("")).exists(isEmpty);
  }
 
  public static void main(final String[] args) {
    for(final String s : args) {
      booleanShow.println(parse(s));
    }
  }
}

A submission by a Java programmer who volunteered:

import java.util.ArrayList;
 
public class IsBalanced {
 
  private Stack stack = new Stack();
 
  public boolean isBalanced(String expression) {
 
    boolean isBalanced = true;
 
    for (int i = 0; i < expression.length(); i++) {
      char nextChar = expression.charAt(i);
 
      if (nextChar == '(') {
        stack.push('(');
      }
      else if (nextChar == '[') {
        stack.push('[');
      } else {
        if (!stack.isEmpty()) {
          char stackChar = (Character) stack.peek();
          if (nextChar == ')') {
            if (stackChar == '(') {
              stack.pop();
            } else {
              return false;
            }
 
          } else if (nextChar == ']') {
            if (stackChar == '[') {
              stack.pop();
            } else {
               return false;
            }
          }
        } else {
          return false;
        }
      }
    }
 
    if (!stack.isEmpty()) {
      isBalanced = false;
    }
    return isBalanced;
 
 
  }
 
  public static void main(String[] args) {
    System.out.println(args[0]);
    System.out.println((new IsBalanced()).isBalanced(args[0]));
  }
 
  private class Stack {
 
    private ArrayList stack = new ArrayList();
 
    public void push(char c) {
      stack.add(c);
 
    }
 
    public void pop() {
      stack.remove(stack.size()-1);
    }
 
 
    public Object peek() {
      return stack.get(stack.size()-1);
    }
 
    public boolean isEmpty() {
      return stack.size() == 0;
    }
  }
}

Forget the syntax for a moment and consider the compositional properties of each of these programs. For example, what if I were to add another pair of brackets such as '{' and '}'? Are there sub-programs that exist independently and can be extracted from the larger program? How does that affect my ability to reason (and therefore, read) the code?

What properties about the code make it easy to read?

Proving the existence of curry

Friday, September 5th, 2008

Prove ∀A. ∀B. ∀C. ((A∧B)→C)→A→B→C with a truth table.

WTF does that mean? It means that for any three propositions (A, B, C), then the conjunction (logical AND) of A and B implies C implies A implies B implies C. Note that → is right-associative, so X→Y→Z is the same as X→(Y→Z). If you are unfamiliar with denotational semantics (these crazy symbols), then perhaps this more relaxed notation makes sense forall A B C. ((A, B) -> C) -> A -> B -> C. Remember this notation, because we will use it later.

Here are some truth tables for conjunction and implication to get started:

Conjunction
P  Q  P∧Q
0  0  0
0  1  0
1  0  0
1  1  1

Implication
P  Q  P→Q
0  0  1
0  1  1
1  0  0
1  1  1

We can prove the truth of the above statement by observing a tautology (all true values) in a truth table.

1  2  3  4    5        6    7      8

A  B  C  A∧B  (A∧B)→C  B→C  A→B→C  ((A∧B)→C)→A→B→C
0  0  0  0    1        1    1      1
0  0  1  0    1        1    1      1
0  1  0  0    1        0    1      1
0  1  1  0    1        1    1      1
1  0  0  0    1        1    1      1
1  0  1  0    1        1    1      1
1  1  0  1    0        0    0      1
1  1  1  1    1        1    1      1

Observe that column 8 is true. Therefore ∀A. ∀B. ∀C. ((A∧B)→C)→A→B→C is a true statement.

Remember this statement earlier forall A B C. ((A, B) -> C) -> A -> B -> C? If you have GHCi installed, go to the prompt and type :set -fglasgow-exts. Then ask for the type of the curry function :type curry. You will see this:

Prelude> :type curry
curry :: forall a b c. ((a, b) -> c) -> a -> b -> c

Same same! :)

OK, so Haskell is for crazy people who use (oh dear!) logic which has nothing to do with that real world and they should all be writing enterprise Java applications like real programmers, right? Yeah right. Yep uh huh.

So let’s write this in Java, just for kicks and just to be noisy. Start with the conjunction and implication primitives:

interface Implication<P, Q> {
  Q implies(P p);
}
 
interface Conjunction<P, Q> {
  P p();
  Q q();
}

Next write the method for representing the aforementioned statement:

class S {
  static <A, B, C> Implication<Implication<Conjunction<A, B>, C>, Implication<A, Implication<B, C>>> s() {
    return null; // todo
  }
}

I shall leave it as a reader exercise to implement the s method. I assure you of only one possible implementation if you do not use null, exceptions or side-effects.

Function currying, like all programming concepts, is a logical statement under the Curry-Howard Isomorphism. Have a nice day :)

Sorry Ben

Sunday, August 31st, 2008

Ben,
You have left two comments here, the second of which asked where your previous comment went. They were both caught by a spam filter and I am certain I pressed Approve on the first one and I definitely did on the second, but alas, they disappeared (WTF?).

Sorry about that, but if you could repost them, I will endeavour to ensure that they appear, since if I remember rightly, your original comment was a question of curiosity. Maybe the Wordpress guys can tell me why this is happening.

Flippin’ Scala

Friday, August 22nd, 2008

Once upon a time, I tried to write some Scala 2.7.1 for Functional Java and Reductio, but the compiler broke. So I filed the bug and waited for a fix. Thanks to Odersky et. al., the fix came promptly, so I started using one of the Scala 2.7.1->2.7.2 nightly builds and then I could compile my Scala code, yay! But that didn’t stop users complaining about crashes when using Scala 2.7.1 due its bad class file parser. Some users even stopped using Reductio because they don’t trust non-release builds. Oh well.

So I try out this new code snippet, nothing complicated:

class Foo[F[_]]
 
object Foo {
  def foo(n: Int)(implicit f: Foo[IN] forSome { type IN[_] }) = "foo"
 
  implicit val z: Foo[List] = new Foo[List]
 
  val t = foo(7)
}

But Scala 2.7.1 falls over. So does the 2.7.1->2.7.2 nightly build that I was using. Ugh! So I try out Scala 2.7.2-RC1, yay it compiles my legitimate source file. But does it compile all my other source?

Er no, Scala 2.7.2-RC1 produces bad class files when compiling code that is otherwise fine with previous Scala versions. In an attempt to obtain one bug fix I have also had to adopt another — one that makes its use non-viable. I am stuck with dealing with the former bug, which is also somewhat non-viable but only slightly more so than the latter. Give me a friggin’ break!

Ugh, this is not the first occurrence of this silliness. Flippin’ Scala, does this shit ever stop?

Introductory C-H and Static Typing

Friday, August 15th, 2008

We use logic every day. No, I don’t mean just us programmers; I mean all of us. Here is an observation about propositional logic:

I have three propositions P, Q and R.

It doesn’t matter what these three propositions actually are, it will always hold that, “if P then Q implies that if Q then R implies that if P then R”.

I’ve subverted that a little to try to make it read a little better, but perhaps look it at it a bit more formally:

forall P Q R. (P → Q) → (Q → R) → (P → R)

You might like to try it out on paper using some example propositions, such as:

  • P = Today is Tuesday
  • Q = I am going swimming
  • R = I have hairy armpits

I won’t bastardise it with English again ;) However, I will give you a hint. Here is the truth table for → (logical implication):

A | B | A → B
0 | 0 | 1
0 | 1 | 1
1 | 0 | 0
1 | 1 | 1

Here is where it gets a little interesting. This same logical statement forall P Q R. (P → Q) → (Q → R) → (P → R) can also be expressed in most programming languages. Here it is in Java as the z method:

interface F<A, B> { B f(A a); }
static <P, Q, R> F<P, R> z(F<P, Q> f, F<Q, R> g) { ...

It gets more interesting; there is only one implementation of this function if we assume a terminating subset of the language (for Java, no null or throwing an exception). If you add in a side-effect such as writing to a file or the network, then you have perverted the function signature. Java allows us to do that, so we also have to assume a subset of the language that disallows this unfortunate anomaly. This notion of a type signature having only one implementation is called once inhabited.

Let’s write out the truth table for this. Notice the consistent 1 values in the final column. The statement is a tautology.

P | Q | R | P → R | Q → R | P → R | (Q → R) → P → R | (P → Q) → (Q → R) → P → R
0 | 0 | 0 | 1     | 1     | 1     | 1               | 1
0 | 0 | 1 | 1     | 1     | 1     | 1               | 1
0 | 1 | 0 | 1     | 0     | 1     | 1               | 1
0 | 1 | 1 | 1     | 1     | 1     | 1               | 1
1 | 0 | 0 | 0     | 1     | 0     | 0               | 1
1 | 0 | 1 | 0     | 1     | 1     | 1               | 1
1 | 1 | 0 | 1     | 0     | 0     | 1               | 1
1 | 1 | 1 | 1     | 1     | 1     | 1               | 1

Under the Curry-Howard Isomorphism, logical implication is represented by a function or in the example above using Java, by the F interface. The z function is called function composition. It takes the two give functions/propositions and composes them.

In Haskell, function composition is not called z as we called it with Java, but instead (.). That’s a full-stop character in parentheses. We can ask for the type of (.) in the GHC interpreter:

Prelude> :type (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

We might even call it by passing in function instances (similar to instances of the Java F interface):

Prelude> ((+1) . (*7)) 20
141
 
Prelude> (reverse . map Char.toUpper) "hello there"
"EREHT OLLEH"

You could do the same using Java, but it’s a little more verbose, so I’ll omit that ;)

Here is a simple quiz. If we suppose the same F interface earlier, how many implementations of this function are there:

static <A> F<A, A> t() { ...

What about this one?

static <A, B> F<A, B> u() { ...

Java interop errata

Wednesday, August 13th, 2008

There are a few possibilities for improvement on this Scala Swing Example.

  • Removed unnecessary semi-colons
  • Inlined import
  • Removed = in main declaration (strongly advised on functions returning Unit and especially more for main)
  • Removed a few unnecessary parentheses
import javax.swing._
import java.awt.event.{ActionEvent, ActionListener}
 
object HelloWorld extends JFrame("Hello Swing") {
  def showButtonMessage(msg: String)  =
    JOptionPane.showMessageDialog(null, String.format("""<html>Hello from <b>Scala</b>. Button %s pressed""", Array(msg)));
 
  def main(args: Array[String]) {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
    val button = new JButton("Click Me")
    button.addActionListener((e:ActionEvent) => showButtonMessage(e.getActionCommand.toString))
    getContentPane add button
    pack
    setVisible(true)
  }
 
  implicit def actionPerformedWrapper(func: (ActionEvent) => Unit) = new ActionListener {
    def actionPerformed(e:ActionEvent) = func(e)
  }
}