Scripting COM comp onents in Haskell

Simon Peyton Jones simonpjdcsglaacuk Erik Meijer erikcsruunl

University of Glasgow University of Utrecht

Daan Leijen leijenwinsuvanl

University of Amsterdam

Abstract system higher order functions lazy evaluation and

convenient syntax In particular we describ e an

The expressiveness of higherorder typed languages

interface b etween Haskell and s Comp onent

such as Haskell or ML makes them an attractive

Ob ject Mo del COM that makes it easy to script

medium in which to write software comp onents Hith

COM comp onents from a Haskell program We make

erto however their use has b een limited by the all

two main contributions

ornothing problem it is hard to write just part of an

application in these languages

 We describ e a graceful and stronglytyped inte

Comp onentbased programming using a binary stan

gration of COM into Haskell

dard such as Microsofts Comp onent Ob ject Mo del

 If the exercise is to b e more than just Gosh we

COM oers a solution to this dilemma by sp ecify

can script COM in Haskell as well as in Visual

ing a languageindep endent interface b etween comp o

Basic then it is imp ortant to demonstrate some

nents This pap er rep orts ab out our exp erience with

added value from using a higherorder typed lan

exploiting this opp ortunity in the purelyfunctional

guage We oer such a demonstration in the form

language Haskell We describ e a design for integrat

of an extended case study

ing COM comp onents into Haskell programs and we

demonstrate why someone might want to script their

COM comp onents in this way

We are also excited by the dual p ossibility that of

writing COM comp onents in Haskell but that is b e

This paper appears in the Proceedings of the Fifth In

yond the scop e of this pap er

ternational Conference on Software Reuse Victoria

British Columbia June

Background

This version includes an Appendix that is omitted from

Until recently it has b een much easier for a client pro

the published paper

gram to use software comp onents libraries classes

abstract data types written in the same language

Introduction

One of the attractive features of the current vogue for

The sp ecication of the interface b etween the

comp onentbased programming is its language inde

comp onent and its clients is usually given in a

p endence Instead of having to write an entire ap

languagesp eci way for example as C header

plication in a single language it b ecomes p ossible to

les or C class descriptions

write each software comp onent in the most suitable

The b etween client and com

language available This p ossibility presents new op

p onent is often languagesp ecic or p erhaps even

p ortunities to comp onent implementors

unsp ecied b ecause b oth client and comp onent

In this pap er we prop ose the purelyfunctional lan

are assumed to b e compiled with the same com

guage Haskell as an attractive language for com

piler

p onent scripting that is for constructing new comp o

nents by gluing together other standard comp onents Programmers can assume a rather intimate cou

Haskell supp orts a number of features that make this pling b etween the address spaces of client and

b oth secure and expressive a rich p olymorphic type comp onent for example the client might pass a

How COM works p ointer into the middle of an array to b e side

eected by the comp onent

Although there are many very fat b o oks ab out COM

eg the core technology is quite simple a no

COM encapsulates a software comp onent in a way

table achievement This section briey introduces the

that contrasts with each of these three asp ects

key ideas We concentrate exclusively on how COM

works rather on why it works that way the COM

 The interface b etween client and comp onent is

literature deals with the latter topic in detail

sp ecied in IDL COMs Interface Denition Lan

guage For each particular language to ols are

Here is how a client written in C might create and

provided to convert IDL into the corresp onding

invoke a COM ob ject

sp ecication in that language section

Create the object

 COM sp ecies the clientcomponent interface at

errcode CoCreateInstance clsid

a binary level indep endently of any particular

ifaceid

language or section

ifaceptr

 Parameters are exp ected to b e marshalled from

if not SUCCEEDEDerrcode

the clients address space to the comp onents ad

error recovery

dress space and vice versa Sometimes the two

share an address space in which case marshalling

need do no copying but all COMcalls provide

Invoke a method

enough information to do such marshalling

ifaceptr ifaceptr x y z

 Interfacing b etween two languages often carries

The pro cedure CoCreateInstance is b est thought of

p erformance overheads b ecause of diering data

as a In real life it takes more parame

representation and memoryallo cation p olicies

ters than those given ab ove but they are unimp ortant

When the alternative is a nativelanguage inter

here Calling CoCreateInstance creates an instance

face b etween client and comp onent these extra

of an ob ject whose class identier or CLSID is passed

overheads can seem rather unattractive

in clsid The class identier is a bit globally

However anyone using COM has already bitten

unique identier or GUID Here globally unique

the bullet they have declared themselves willing

means that the GUID is a name for the class that will

to accept a hit in programming convenience and

not ever b e reused for any other purp ose anywhere

p erhaps a hit in p erformance for marshalling in

on the planet A standard utility allows an unlimited

exchange for the advantages that COM brings

supply of fresh GUIDs to b e generated lo cally based

on the machines IP address and the date and time

The ab ove p oints are not COMs only advantages

The co de for the class is found indirectly via the sys

For example one of the primary motivations for using

tem registry which is held in a xed place in the

COM concerns version control and upgrade paths for

le system This double indirection of CLSIDs and

software comp onents which we have not mentioned

registry makes the client co de indep endent of the

at all However these additional prop erties are well

sp ecic lo cation of the co de for the class Next

describ ed elsewhere and do not con

CoCreateInstance loads the class co de into the cur

cern us further in this pap er except in so far as they

rent pro cess unless it has already b een loaded al

serve as motivators for p eople to write and use COM

ternatively one can ask COM to create a new pro cess

comp onents

either lo cal or remote to run the class co de Finally

Also COM is not alone in having these prop erties

COM asks the class co de more precisely the class

Numerous research pro jects had similar goals in par

factory to create an instance of the class which it

ticular CORBA In fact much of the rest of this

returns to the caller In fact what is returned is an

pap er would apply to CORBA as well as COM Un

interface pointer which we discuss next

like COM though CORBA is not a binary standard

to use CORBA for Haskell would required adding a

Interfaces and metho invocation

language binding for Haskell to some manufacturers

ORB COM is much friendlier to nonmainstream lan A COM ob ject supp orts one or more interfaces each

guages of which has its own globallyunique interface iden

that p oints to the structures just describ ed the client

b e happy "Vtbl pointer" "Virtual function table" will

(not shared) (shared by all instances)

p ointers provide the sole way in which one Interface Interface

QueryInterface

interact with a COM ob ject This restriction

pointer can

it p ossible to implement location transparency

AddRef makes

a ma jor COM warcry whereby an ob jects client in

Release

with the ob ject in the same way regardless of

Object teracts

or not the ob ject is in the same address space

state other whether

even on the same machine as the client All that

methods or

is necessary is to build a proxy interface p ointer that

does p oint into the clients address space but whose

metho ds are stub pro cedures that marshal the data

across the b order to and from the remote ob ject

Figure Interface p ointers

Getting other interfaces

A single COM ob ject can supp ort more than one inter

face But as we have seen b efore CoCreateInstance

tier or I ID That is why CoCreateInstance takes

returns only one interface p ointer So how do we

a second parameter ifaceid the I ID of the de

get the others Answer every interface supp orts the

sired interface CoCreateInstance returns the inter

QueryInterface metho d which maps an I ID to an

face pointer of this interface in ifaceptr There is

interface p ointer for the requested I ID or fails if the

no such thing as an ob ject p ointer or ob ject iden

ob ject do es not supp ort the requested interface So

tier there are only interface p ointers

from any interface p ointer ifaceptr on an ob ject

we can get to any other interface p ointer ifaceptr

The I ID of an interface uniquely identies the com

which that ob ject implements for example

plete signature of that interface that is what metho ds

ifaceptr ifaceptr iid ifaceptr

the interface has including what order they app ear

in their calling convention what arguments they

Why Because QueryInterface is at oset

take and what results they return If we want to

in every interface

change the signature of an interface we must give the

new interface a dierent I ID from the old one That

The COM sp ecication requires that QueryInterface

way when a client asks for an interface with a particu

b ehaves consistently The IUnkown interface on

lar I ID it knows exactly what that interface provides

an ob ject is the identity of that ob ject queries

for IUnknown from any interface on an ob ject

A COM interface p ointer is deep breath a p ointer to

should all return exactly the same interface p ointer

a p ointer to a table of metho d addresses Figure

Queries for interfaces on the same ob ject should

Notice the double indirection which allows the table

always fail or always succeed Thus the call

of metho d addresses to b e shared among all instances

ifaceptrifaceptr iidifaceptr

of the class Data sp ecic to a particular instance of

should not succeed at one p oint but fail at another

the class notably the ob jects state can b e stored at

Finally the set of interfaces on an ob ject should form

some xed oset from the vtbl p ointer Figure

an equivalence relation

The format of this information is entirely up to the ob

jects implementation the client knows nothing about

Reference counting

it Lastly when a metho d is invoked the interface

p ointer must b e passed as the rst argument so that

Each ob ject keeps a reference count of all the inter

the metho d co de can access the instancesp ecic state

face p ointers it has handed out When a client dis

Taking all these p oints together we can now see why

cards an interface p ointer it should call the Release

a metho d invocation lo oks like this

metho d via that interface p ointer every interface sup

p orts the Release metho d Similarly when it dupli

ifaceptr ifaceptr x y z

cates an interface p ointer it holds the client should

call the AddRef metho d via the interface p ointer ev None of this is language sp ecic That is COM is

ery interface also supp orts the AddRef metho d When a binary interface standard Provided the co de that

an ob jects reference count drops to zero it can com creates an ob ject instance returns an interface p ointer

object uuidC

pointerdefaultunique Application

interface IUnknown

HRESULT QueryInterface in REFID iid

out void ppv

Green

AddrRef void

ULONG .idl M.hs Com.hs

Release void

ULONG Card

Figure The IUnknown interface in IDL

Figure The big picture

mit suicide but it is up to the ob ject not the client

to cause this to happ en All the client do es is make

correct calls to AddRef and Release

C world adding yet another level of indirection and

are accessed in the Haskell world using our previously

Describing interfaces

developed foreign language interface to C Green

Card automatically generates all required stub pro ce

Since every I ID uniquely identies the signature of

dures and marshalling co de to call C The Mhs mo d

the interface it is useful to have a common language

ule together with a Haskell mo dule Comhs

in which to describ e that signature COM has such a

is all that an application need imp ort to access and

language called IDL Interface Denition Language

manipulate all the COM ob jects describ ed by M

although IDL is not part of the core COM stan

dard You do not have to describ e an interface using

What Green Card generates

IDL you can describ e it in classical Greek prose if you

like All COM says is that one I ID must identify one

So what do es the Haskell mo dule M exp ort

signature

Describing an interface in IDL is useful though b e

 For each CLSID Baz in the IDL mo dule mo dule

cause it is a language that all COM programmers

M exp orts a value baz of type ClassId This value

understand Furthermore there are to ols that read

represents the CLSID of class Baz ClassId is an

IDL descriptions and pro duce languagesp ecic dec

abstract type exp orted by Comhs

larations and glue co de For example the Microsoft

 For each I ID IFoo in the IDL mo dule M exp orts

MIDL compiler can read IDL and pro duce C class

declarations that make COM ob jects lo ok exactly like

{ A new abstract Haskell data type IFoo

C ob jects or Java or

Surprisingly no op erations are provided on

As a short example Figure gives the IDL description

values of type IFoo

of the IUnknown interface the interface of which every

{ A value iFoo of type Interface IFoo

other is a sup erset The bit long constant is the

This value represents the I ID for IFoo

GUID for the IUnknown interface

Interface is an abstract type constructor

exp orted by Comhs

Interfacing Haskell and COM

An interface p ointer for an interface whose I ID

Our goal is to provide a convenient and typesecure

is IFoo is represented by a Haskell value of type

interface b etween a Haskell program and the COM

Com IFoo Com is an abstract type constructor

ob jects it manipulates How could COM ob jects ap

exp orted by Comhs

p ear to the Haskell programmer

interrogates the type library for M a COM ob ject generated by

Our approach illustrated in Figure is broadly con

a Microsoft to ol from the IDL The Microsoft to ol do es all the

ventional We have built a to ol called Green Card

parsing and typechecking of the IDL The typelibrary ob ject

that takes an IDL mo dule Midl and from it generates

it pro duces is essentially a parse tree with metho ds that allow

1

its clients to navigate the parse tree The to ol itself is written

a Haskell mo dule Mhs Ob ject instances live in the

in Haskell and has b een b o otstrapp ed to generate the Haskell

1

In fact rather than reading the IDL text directly the to ol mo dule to access type library comp onents

 For each metho d meth in the interface IFoo mo d queryInterface Interface j

ule M exp orts a Haskell function meth with the Com i

type IO Com j

meth a a Com IFoo IO r

1 n

The rst argument is the I ID for the desired in

terface The second is the interface on which

Here a a are the argument types exp ected

1 n

we want to query for another interface The

by meth extracted from the metho ds IDL signa

result is an interface for the desired interface

ture and r is its result type If there are many

Again we use p olymorphism to make sure that

results then meth would have a tuple result type

the interface that is returned by queryInterface

IO r r The interface p ointer is passed

1 n

of type Com j corresp onds to the I ID of type

as the last argument for reasons we discuss later

Interface j passed as the rst argument

Notice that meth cannot b e invoked on any inter

 There are no programmervisible pro cedures cor

face p ointer whose type is other than Com IFoo

resp onding to AddRef and Release Instead

so the interface is typesecure

when Haskells garbage collector discovers that a

The result of meth has type IO r rather than

value of type Com i is now inaccessible it calls

simply r to signal that meth might p erform

Release on the interface p ointer it encapsulates

some inputoutput In Haskell a function that

This is just a form of nalization a wellknown

has type Int Int say is a function from in

technique in which the garbage collector calls a

tegers to integers no more and no less In particu

userdened pro cedure when it releases the store

lar it cannot p erform any inputoutput All func

held by an ob ject

tions that can p erform IO have a result type of

the form IO which should b e read the type of The ability to do nalization is not a standard

IOp erforming computations returning a value

feature of Haskell but it is readily added to a

of type This socalled monadic IO has b e

garbagecollected language There is a time de

come the standard way to do inputoutput in lay b etween when the program ceases to use an

purely functional languages We will see an

ob ject and when the garbage collector discovers

example of how to use values of IO type in Sec this fact for critical resources whose immediate

tion

release is essential the ob ject can instead b e freed

explicitly by the programmer by calling Release

 The library mo dule Comhs provides a generic

pro cedure createInstance

The Agent example

createInstance ClassId

These p oints make more sense in the context of a par

Interface i

ticular example Supp ose we to ok the IDL description

IO Com i

for Microsoft Agent After b eing pro cessed by Green

Card we would have a Haskell mo dule Agenths that

Like CoCreateInstance it takes a CLSID and

exp orts among other things the types functions and

and I ID and returns an interface p ointer Unlike

values given in Figure

the C pro cedure CoCreateInstance however

we use p olymorphism to record the fact that the

Microsoft Agent implements carto on characters that

interface p ointer returned corresp onds to the

p op up on the screen and talk to you The ani

I ID passed as argument This somewhat un

mation is supp orted by an agent server whose CLSID

usual use of p olymorphism elegantly captures ex

is agentServer and whose main interface is IAgent

actly what we want to say given an I ID of type

Once we have created an agent server we can load

Interface it guarantees to return an interface

a character from a le getting a CharId in reply

p ointer of type COM The typically implicit link

Now we can generate instances of that character us

age b etween the I ID and the corresp onding inter

ing getCharacter getting an interface p ointer for the

2

face p ointer has b een made explicit in the type

character in return Having got a character we can

The IO type has an exception mechanism that is

2

It is quite common for COM calls to return interfaces Here

used to deal with the failure of createInstance

getCharacter plays the role of createInstance returning an

interface to the new character The interface may b e have b een

 The library mo dule Comhs provides a generic

created inside the agent server by a call to CoCreateInstance

but that do es not concern us pro cedure queryInterface

module Agent where

The Agent class

agentServer ClassID

The IAgent interface

data IAgent Agent interface type

iAgent Interface IAgent and its IID

type CharId Int

load String Com IAgent IO CharId

getCharacter CharId Com IAgent IO Com IAgentCharacter

etc other methods of IAgent

The AgentCharacter interface

data IAgentCharacter Ditto IAgentCharacter

iAgentCharacter Interface IAgentCharacter

type ReqId Int

play String Com IAgentCharacter IO ReqId

speak String Com IAgentCharacter IO ReqId

wait ReqId Com IAgentCharacter IO ReqId

etc other methods of IAgentCharacter

Figure Exp orts from mo dule Agenths

make it talk a sentence by calling speak or play a a ab b

little animation by calling play x f f x

Here is a complete example program

It is used here to allow us to write the inter

face p ointer rst in a metho d call much as hap

module Main where

p ens in an ob ject oriented language For exam

import Agent

ple robby speak Hello means the same as

speak Hello robby It is for this reason that

main comRun

Green Card arranges that the interface p ointer is

do server createInstance

the last parameter of each metho d call

agentServer iAgent

robid server load robbyacs

 The do notation is used to sequence a series of

robby server getCharacter robid

IOp erforming function calls It is much more

robby moveTo centerScreen

syntactically convenient than using the bind and

robby show

unit functions of the monad as the rst pap ers

robby speak Hello world

ab out monadic IO did For example the

statement

To make sense of this we need to know the following

Haskell lore

robby server getCharacter robid

 Left asso ciative function application is written as

p erforms the action server getCharacter

juxtap osition Thus f a b means f applied to a

robid and binds its result to the name robby

and b Right asso ciative function application is

written as Thus f g a means f applied to

Now we can read the example The function comRun

g a

is exp orted by Comhs and has type

 The function is simply reverse function applica

tion comRun IO a IO

It encapsulates a computation that accesses COM do agent speak La la la

preceding it with initialization and following it with agent play Dance

nalization

Here we have dened the type Action as a shorthand

Next the call to createInstance creates an instance to denote actions that can b e p erformed by an agent

of the agent server The next two lines load the anima like play Dance or dancesAndSings

tion le robbyacs and create one instance of the

In C or Java one could dene dancesAndSings

character The curious intermediate value robid is

as the metho d of a class that inherits from

an artifact of the Agent server design and not relevant

IAgentCharacter using implementation inheritance

here In practice we would abstract from this design

to arrange to call the characters own play or speak

quirk and dene a new function createCharacter as

pro cedure To us it seems rather unnatural to intro

createCharacter String Com IAgent duce a type distinction b etween agents that can dance

IO Com IAgentCharacter and sing and agents that can danceAndSing Ob ject

createCharacter agent server oriented languages are go o d in expressing new ob jects

do a server load agent as extensions of existing ob jects functional languages

server getCharacter a are go o d in expressing new functions in terms of ex

isting functions In Visual Basic we could certainly

Finally the character app ears in the center of the

dene a pro cedure like dancesAndSings but than we

screen and is asked to sp eak a phrase

could only call it using a dierent syntax from native

metho ds calls

Performance

Sub DancesAndSings Byref Agent

In the past functional languages have had a reputation

AgentSpeak La la la

for slow execution That is no longer the case Com

AgentPlay Dance

piled Haskell programs run b etween and times

End Sub

slower than their C counterparts dep ending on the

application and faster than typical interpreted lan

RobbySpeak Hello

guages For scripting applications the p erformance of

DancesAndSings Robby

the Haskell program is most unlikely to b e an issue

If the sequence of actions a particular agent has to

Why use Haskell

p erform gets long it b ecomes a bit tiresome writing all

the agent parts so we can rewrite the denition

One can of course invoke COM ob jects from Visual

as a little script like this

Basic or C In this section we show how one can

easily build rather expressive Haskell libraries on top

dancesAndSings Action

of the interface we have seen so far These li

dancesAndSings agent

braries make extensive use of higherorder functions

agent sequence speak La la la

and have simple algebraic prop erties

play Dance

Extending the characters rep ertoire

where sequence is a reusable function that executes

The metho ds play and speak are rather limited We

a list of actions from left to right

would like to b e able to dene new comp ound metho d

so that

sequence Action Action

sequence a agent agent a

robby dancesAndSings

sequence aas agent

do agent a sequence as agent

would make robby execute a sequence of play and

speak actions Heres how we can do that in Haskell

Notice that the type of the rst argument of sequence

is a list of functions that return IO performing com

type Action

putations The ability to treat functions and compu

Com IAgentCharacter IO ReqId

tations as rstclass values and to b e able to build

and decomp ose lists easily has a real payo In Java

dancesAndSings Action

C or VB it is much harder to dene custom con

dancesAndSings agent

trol structures such as sequence For example in Java agent movePath circle

one would use the package javalangreflect to where

reify classes and metho ds into rst class values or use circle x radiuscos t

the Command pattern to implement a command y radiussin t

interpreter on top of the underlying language Note

that in our case sequence is another comp os t pipi

ite metho d on agents just as dancesAndSings and is

called in exactly the same way as a native metho d

By reusing sequence and movePath we were able to

The low cost of abstraction in Haskell is even more dene moveSquare and moveCircle very easily

convincing when we dene a family of higherorder

functions to ease moving agents around the screen

Synchronization

First we dene a function movePath as

The Agent server manages each character as a sep

type Pos IntInt

arate sequential pro cess running concurrently with

the other characters Supp ose we want one character

movePath Pos Action

to sing while the other dances we just write

movePath path agent

agent sequencemap moveTo path

do erik sings

simon dances

Function movePath path robby moves agent robby

along all the p oints in the list path In Visual Basic

It lo oks as if these take place sequentially but actu

or Java we can dene a similar function quite easily

ally they are done in parallel Each character main

as well by using the builtin For Each Next

tains a queue of requests it has got from the server

control structure

and p erforms these in sequence Hence a call such as

erik sings returns immediately while erik is still

Sub MovePath Byref Agent Byref Path

singing and then makes simon dance in parallel

For Each Point In Path

AgentMoveTo Point

Now supp ose we want daan to do something else only

Next point

when b oth erik and simon have terminated how can

End Sub

we ask the Agent server to do that The answer is that

every Action returns a request ID of type ReqId on

However in Haskell we dont have to rely on fore

which any character can wait to synchronize on the

sight of the language designers to built in every con

completion of that request Thus

trol structure we might ever need in advance since we

can dene our own custom control structures on de

do erikDone erik sings

mand Lazy evaluation and higher order functions are

simonDone simon dances

essential for this kind of extensibility

daan wait erikDone

daan wait simonDone

We can use function movePath to construct functions

daan speak Theyre both done

that move an agent along more sp ecic gures such

as squares and circles

You may imagine that in a complex animation it can

b e complicated to get all these synchronizations cor

moveSquare Pos Int Action

rect We might easily wait for the wrong request ID

moveSquare xy width agent

or get deadlo cked or whatever What we would like

agent movePath square

to b e able to do instead is to say something like

where

w width div

erik sings simon dances

square xwyw xwyw

xwyw xwyw

daan speak Theyre both done

xwyw

Here is an inx op erator used to comp ose two an

imations in sequence and comp oses two anima

tions in parallel Since all the synchronization is now

moveCircle Pos Int Action

implicit it is much harder to get things wrong We

moveCircle xy radius agent

can now say what we want since we have abstracted

away from the details of the lowlevel synchronization where

b etween agents action

do reqid action

How can we program these animation abstractions

cast cast waitFor reqid

in Haskell

reqid action

cast cast waitFor reqid

To p erform two animations in sequence we need to

wait until all actions in the rst animation are p er

The op eration waitFor cast reqid makes every

formed b efore we can start the second If we assume

agent a in its input list cast wait on the given request

that an animation returns the requestid of the very

id reqid Function as waitFor reqid always re

last action it p erforms we can wait for that one and

turns reqid

b e sure that all other actions in that animation are

also completed In order to b e able to make an an waitFor Com IAgentCharacter ReqId

imation wait for a requestid we need to know all IO ReqId

characters that will p erform in that animation its waitFor reqid return reqid

cast Hence we represent animations by a pair of aas waitFor reqid

an action that returns a requestid and the cast for do a wait reqid

that action as waitFor reqid

type Anim The denition of parallel comp osition is now easy We

IO ReqId Com IAgentCharacter let all the agents of the second animation wait for the

rst animation to complete and the other way around

Using type Anim we could erroneously try to dene

Note the nice duality in the implementation of the

sequential comp osition of two animations as follows

sequential and parallel combinator we just swap the

middle two statements

action cast action cast

action cast union cast

Anim Anim Anim

where

action cast action cast

action

action cast union cast

do r action

where

cast waitFor r

action

action

do reqid action

reqid action

Unfortunately this solution do es not work b ecause we

cast cast waitFor reqid

can get a deadlo ck when an agent is part of b oth an

cast cast waitFor reqid

imations in which case it could b e waiting for itself

to terminate We therefore take the dierence

In ab out lines of co de we have a very clear denition

b etween the casts involved in the two animations

and implementation of two nontrivial combinators

Using the prop erties of a pure lazy language we can

A more subtle problem o ccurs when more than two an

use equational reasoning to prove various of laws that

imations are comp osed in sequence Supp ose we com

we exp ect to hold for the combinators

p ose three animations thus s s s

and supp ose that agent daan plays a role in s and

s but not s The deadlo ckavoidance device means

x y z x y z

that daan will not wait for s to conclude b efore start

x y z x y z

ing whatever actions are scripted for him in s The

x y y x

solution is a little counterintuitive in the comp o

sition s s make the cast of s who are not

involved in s wait for the the cast of s to nish

Proving prop erties like these is not just a technical

Our nal and correct version of will therefore

nicety As we have already seen obtaining correct syn

b e

chronization among the characters is somewhat sub

tle and conducting pro ofs of prop erties like these can

Anim Anim Anim

reveal nasty bugs This happ ened to us in practice

action cast action cast

when proving the asso ciative law for we discov

action cast union cast

ered that our previous implementation was wrong

What next scripting one would have b een unlikely to come up

with the combinator library describ ed in Section

So far we have describ ed how we may access COM

in any of the ab ove languages

ob jects from a Haskell program The obvious dual is

to encapsulate a Haskell program as a COM ob ject

Acknowledgments

We plan to do this next but there are some interesting

We thank the ICSR referees for their helpful comments

new challenges Chief among these is that a COM

on the pap er We gratefully acknowledge the supp ort

ob ject implemented in Haskell must b e supp orted by

of the Oregon Graduate Institute during our sabbaticals

a Haskell runtime system and garbagecollected heap

funded by a contract with US Air Force Material Com

While the co de might b e shared we would prefer not

mand FC Machines and software were

to create a separate heap for each ob ject remember

supp orted in part by gifts from

a COM ob ject might represent a rather lightweight

thing like a button or a scrollbar Instead we would

References

like all the Haskell ob jects in a pro cess to share the

same runtime system and heap

Kraig Bro ckschmidt Inside OLE second edition

Microsoft Press

Besides encapsulating a Haskell program as a COM

David Chapp el Understanding ActiveX and OLE

ob ject we also plan to encapsulate a Haskell in

Microsoft Press

terpreter as a COM ob ject which implements the

Adam Denning ActiveX Controls Inside Out second

IScriptEngine interface This allows us to use

edition Microsoft Press

Haskell programs to script interactive Web pages

J Peterson editor Rep ort on the programming

SCRIPT LANGUAGEHaskellScript

language HASKELL version Technical rep ort

do yes confirm Do you like Haskell

httpwwwhaskellorg April

document write if yes then Good

Erich Gamma Richard Helm Ralph Johnson and

else Really

John Vlissides Design Patterns AddisonWesley

SCRIPT

Ob ject Management Group The Common Object Re

or as embedded macro language for MS Oce appli

quest Broker Architecture and Specication revision

cations such as Word and Excel

Ob ject Management Group OMG Do cu

ment Number

Summary

AB Hayes Finalization in the collector interface

In EY Bekkers and J Cohen editors Proceedings of

The theme of this pap er is that it is not only possible to

the International Workshop on Memory Management

script COM comp onents in Haskell but also desirable

IWMM St Malo pages Springer Verlag

to do so

LNCS Sept

John Hughes Why Functional Programming Matters

We have describ ed a simple way to incorp orate

Computer Journal

COM ob jects into Haskells type system making

Simon L Peyton Jones and Philip Wadler Imp erative

use of p olymorphism to enforce the connection b e

functional programming In POPL pages

tween an I ID and the interface p ointer returned by

queryInterface We have also shown how one can

Simon Peyton Jones Thomas Nordin and Alastair

use higherorder functions and rstclass computa

Reid Green Card a foreignlanguage interface for

tions that is values of type IO to dene p owerful

Haskell In Proc Haskel l Workshop

new abstractions In the Agent example we built a

SL Peyton Jones and J Launchbury State in Haskell

little customdesigned sublanguage or combinator li

Lisp and Symbolic Computation

brary for expressing parallel b ehavior

Microsoft Press Automation Programmers Reference

All of this can doubtlessly b e done in any program

ming language Mainstream scripting languages such

Microsoft Press Developing for Microsoft Agent

as Tcl and Python provide ways to interface to COM

comp onents and of course one can script comp onents

Dale Rogerson Inside COM Microsoft Press

in Java Visual Basic or C The claim of this pap er

Jon Siegel CORBA Fundamentals and Programming

is simply that a higherorder typed garbagecollected

John Wiley Sons

language such as Haskell can op en up new avenues for

A Pro of of asso ciativity of cc waitFor r

r action

In order to prove that is asso ciative we make some

r cc waitFor r

assumptions ab out Microsofts agent implementation

cc union c waitFor r

The rst assumption is that the call as waitFor r

We rearrange the statements by applying the various

b ehaves like the identity function with a side eect

swap laws

of letting all agents in as wait for request id r We

do r action

assume that waitFor has no other visible side eect

cc waitFor r

It then follows that waitFor distributes over set union

r action

as union bs waitFor r

cc waitFor r

cc union c waitFor r

as waitFor r bs waitFor r

r action

or equivalently that waiting is commutative and idem

cc waitFor r

p otent

cc union c waitFor r

and introduce nesting again

as waitFor r as waitFor r

as waitFor r

do r do r action

cc waitFor r

as waitFor r bs waitFor r

r action

bs waitFor r as waitFor r

cc waitFor r

cc union c waitFor r

The next law states that agents dont have to wait

r action

twice in a row

c union cc waitFor r

as waitFor r as union bs waitFor r

so that nally we can fold the denition of

as union bs waitFor r

actionc actionc

When there is no interaction b etween the set of agents

actionc

that are waiting and the cast of a subsequent action

then waiting can b e delayed

as waitFor r r action

r action as waitFor r

Using the ab ove laws plus standard set theory it fol

lows that is asso ciative

actionc actionc actionc

First we unfold the denition of

do r action

c union cc waitFor r

r do r action

cc waitFor r

r action

cc waitFor r

cc union c waitFor r

Next we atten the sequence of actions

do r action

cc waitFor r

cc union c waitFor r

r action