HOC: A Haskell to Objective-C Binding
Home  | Download  | Examples  | Screenshots  | Documentation  | Support
 HOC: a Haskell to Objective-C bridge


Introduction

HOC is a Haskell to Objective-C binding. In a nutshell, it enables you to use Objective-C objects and frameworks from Haskell, and also enables you to write Objective-C objects in Haskell. The Haskell interfaces produced by HOC are:

  • Strongly Typed
  • While Objective-C is a typed language, it is weakly typed (since it is based on C, which is also weakly typed language), and dynamically typed. Haskell is a statically, strongly typed language, and HOC uses this to its advantage: the Haskell interfaces generated by HOC are heavily typed, and map closely to Objective-C's concepts.

    For example, to allocate a new object, you can send the alloc message to an Objective-C object. More specifically, you are required to send alloc to a class object: [NSMovie alloc], in Objective-C syntax. In HOC, sending alloc to a non-class object is a compile-time error, because alloc is not defined for non-class objects. Of course, since Objective-C uses dynamic binding, HOC still enables you to send arbitrary messages to any object via a generic sendMsg function, but the normal way to send messages to objects with HOC are all strongly typed.

    In practical terms, this means that you gain all the benefits of a modern type system: Haskell's type inference is applied to everything from message sending operations to maintaining an object-oriented class hieararchy. As a result, you produce programs that are safer and work correctly on the first succesful compilation a disturbingly large percentage of the time.

  • Automatically Generated
  • HOC uses an interface generator that parses Objective-C header files to produce Haskell source code. The Haskell code contains data types representing the Objective-C class hierarchy, and methods and selectors which enable HOC to communicate with Objective-C frameworks. If you are familiar with other Haskell interface generators such as c2hs <http://www.cse.unsw.edu.au/~chak/haskell/c2hs/> or GreenCard <http://www.haskell.org/greencard/>, HOC's ifgen tool does the same job, but for creating bindings to Objective-C classes instead.

    By default, HOC is configured to build bindings for the Foundation and AppKit frameworks (collectively named Cocoa on Mac OS X), but you can build your own bindings with ifgen if required.

  • Haskell-Friendly
  • HOC was designed from the very beginning to be as 'Haskell-like' as possible: after all, you are writing Haskell code, not Objective-C code! We make heavy use of key Haskell features such as type classes and partial application, to ensure that you don't have to do evil things like method name mangling or understand a whole new bunch of syntax, just to do something simple like embed an NSMovie in your application.

HOC's primary platform is Mac OS X, Apple's modern UNIX-based operating system. However, HOC does provides preliminary support for the GNUstep platform <http://www.gnustep.org/>, and has been lightly toasted, err, tested, with GNUstep on Linux.

Requirements

HOC requires the Glasgow Haskell Compiler (GHC) 6.2 <http://www.haskell.org/ghc/> or later to build. We use the latest features provided by GHC, such as Template Haskell, to implement many parts of HOC, and it would be impossible (as opposed to just plain hard) to port these implementations to work with older versions of GHC.

Assumed Knowledge

Let's get something straight here: HOC isn't for the beginner Haskell or Objective-C developer. You are required to know basic Objective-C concepts such as what classes, methods, messages and selectors are, and ideally will have written a few Objective-C programs to understand how to use all these concepts in practice. You should also be comfortable with programming in Haskell, in particular how to program with IO in Haskell (meaning that you should have actually written a few Haskell tools which use IO). That doesn't mean you have to understand monads, by the way. Hell, this author has done IO in Haskell for years and doesn't pretend to understand monads ...


Quick Start

A Simple Commandline Tool

Apple provides the source code for a ``Simple Cocoa Command-Line Tool'', which performs uniquing and sorting on a list of arguments. You can find the original code at: http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaObjects/Articles/SimpleCocoaTool.html

To give you an idea of what HOC code looks like, here's a line-by-line translation of the Objective-C code that's as close to the original as we can get (even trying to do silly things like emulate a while() loop):

  module Main where
  -- #import <Foundation/Foundation.h>
  import Foundation
  import Foundation.NSProcessInfo (arguments)
         -- We need this import to disambiguate the 'arguments'
         -- function: an 'arguments' method is defined in many
         -- classes, including NSProcessInfo, NSScriptCommand,
         -- and NSTask.  Any ambiguous functions are not exported
         -- by the framework by default: you will need to
         -- import those functions explicitly.
  import HOC
  -- int main (int argc, const char * argv[]) {
  main = do
  --   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  --   ...
  --   [pool release];
       withAutoreleasePool main'
  main' = do
  --   NSArray *args = [[[NSProcessInfo processInfo] arguments];
       args <- _NSProcessInfo # processInfo >>= arguments
  --   NSCountedSet *cset = [[NSCountedSet alloc] initWithArray:args];
       cset <- _NSCountedSet # alloc >>= initWithArray args
  --   NSArray *sorted_args = [[cset allObjects]
  --     sortedArrayUsingSelector:@selector(compare:)];
       sorted_args <- cset # allObjects
         >>= sortedArrayUsingSelector (getSelectorForName "compare:")
  --   NSEnumerator *enm = [sorted_args objectEnumerator];
       enm <- sorted_args # objectEnumerator
  --   id word;
  --   while (word = [enm nextObject]) {
  --     printf("%s\n", [word UTF8String]);
  --   }
       let loop = do
           word <- enm # nextObject
           if (not (isNil word))
             then do { putStrLn ( (fromNSString.castObject) word ); loop }
             else do return ()
           in
               loop
  --   [cset release];
       -- Don't need to release anything: HOC manages memory for you via
       -- Haskell's garbage collector!
  --   return 0;
       return ()
  -- }

The code is available in the Samples/UniqSort/ directory of the HOC source distribution if you'd like to compile it and try it for yourself:

  ~hoc/Samples/UniqSort % ./uniqsort a z c a l q m z
  /Users/... # This appears because it's part of the program's
             # argument list!
  a
  c
  l
  m
  q
  z

Hopefully, the code listing above will give you a good idea about how to write Haskell code that sends messages to Objective-C objects. For more detail, see the chapter on Mapping Objective-C Concepts to Haskell.

A Simple GUI Application

Preface: This section presumes that you've written a Cocoa application before with Objective-C, so that you understand the basic development process and design patterns involved with Cocoa programs, such as Model-View-Controller and how to use Interface Builder. If you don't know any of this, you'll have to do some background reading on Cocoa. Apple provides a simple tutorial at http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/index.html, but if you're after something more comprehensive, this author has read and highly recommends the book ``Cocoa Programming for Mac OS X'', by Aaron Hillegass: http://www.bignerdranch.com/products/cocoa1.shtml.

Say you've got a simple Haskell module: for this example, we'll use the ExpressionParser.hs module from the Samples/ExpressionParser directory of the HOC source distribution. The code is short and schweet:

  module ExpressionParser
  where
  import Text.ParserCombinators.Parsec
  import Text.ParserCombinators.Parsec.Expr
  expr :: Parser Integer
  expr = buildExpressionParser table factor <?> "expression"
  table = [ [op "*" (*) AssocLeft, op "/" div AssocLeft]
          , [op "+" (+) AssocLeft, op "-" (-) AssocLeft] ]
    where
      op s f assoc = Infix (do { string s; return f }) assoc
  factor = do { char '('; x <- expr; char ')'; return x }
           <|> number
           <?> "simple expression"
  number :: Parser Integer
  number = do { ds <- many1 digit; return (read ds) } <?> "number"

Now, you want to wrap a GUI around this module so that people can use it without loading GHC or the Apple Terminal application: see http://localhost/~andrep/hoc/screenshots/ExpressionParser_view.png for a screenshot of what the GUI will look like. From a programing perspective, the GUI consists of:

An expressionEntry outlet
This is where the user types in the expression which they want the answer to.

An evaluateExpression action
The method which will be called when the user clicks on the button, or presses Enter in the expressionEntry text field.

An evaluation outlet
Where the answer to the expression evaluation will be displayed.

For this example, we assume that you've created and instantiated an EPController object in Interface Builder which the GUI view will be connected to. The question is, of course: how do you write this EPController object in Haskell? The answer: like this ...

  {-# OPTIONS -fglasgow-exts #-}
  module EPController where
  import Cocoa hiding (parse)
  import ExpressionParser
  import Selectors
  import Text.ParserCombinators.Parsec (parse)
  $(declareClass "EPController" "NSObject")
  $(exportClass "EPController" "ep_"
    [ Outlet "expressionEntry" [t| NSTextField () |]
    , Outlet "evaluation"      [t| NSTextField () |]
    , InstanceMethod Selectors.info_evaluateExpression ])
  obj #. var = obj # getIVar var
  ep_evaluateExpression _ self = do
    -- Get the expressionEntry outlet text field from this object, and get
    -- what the user typed as a Haskell string
    expression <- self #. _expressionEntry >>= stringValue >>= haskellString
    -- Parse the expression
    case (parse expr "" expression) of
      Left err ->
        -- Parsing returned an error: display it in the output text field      
        self #. _evaluation >>= setStringValue (toNSString $ "Error " ++ show err)
      Right answer ->
        -- Parsing was successful: display the answer
        self #. _evaluation >>= setStringValue (toNSString $ show answer)

Additionally, you'll need to write a Selectors.hs module, which contains any additional selector names that aren't in Cocoa. This enables HOC to statically type check your function names and make sure that they exist. You can call the module whatever you like: the important bit is that the declareSelector function you'll be using must be in a different module from the declareClass and exportClass functions, due to a limitation of Template Haskell. e.g.:

  {-# OPTIONS -fglasgow-exts #-}
  module Selectors where
  import AppKit.NSButton
  $( declareSelector "evaluateExpression:" [t| forall a. NSButton a -> IO () |] )

That comprises the code for your graphical application. You'll still need to produce a .app application bundle to run your GUI application though: to do this, you could manually make the .app bundle, which is rather tedious. A better idea would be to use Xcode to generate a boilerplate bundle for you and customise that, or steal one of the directory layouts from one of HOC's sample applications (in the Samples/ directory). Once you've produced the Contents/ directory layout required for the bundle, you can then use the hocwrap tool (described in the Tools section) to wrap your Haskell executable in the final .app directory (or hand-roll it yourself, if you're into masochism).

For complete code examples, see the ExpressionParser, Browser, and Editor applications in HOC's Samples/ directory.


Mapping Objective-C Concepts to Haskell

Objects & Classes

Classes

An Objective-C class foo has a corresponding Haskell type foo (): the type signature for a function which takes in an NSArray (and only an NSArray) and outputs an NSMovie will look like NSArray () -> NSMovie ().

To permit a function to use a NSArray or any of its subclasses such as NSMutableArray (which is the behaviour you'd expect from an object-oriented language), use a type variable in place of the (): e.g. NSArray a.

Class Objects

Class objects are represented in HOC by preprending an underscore to the class name: _classname. For example, to send the alloc message to the NSMovie class object, write _NSMovie # alloc.

Protocols & Protocol Adoptions

This section of the documentation hasn't been written yet, but in the meantime, you may find the following note from Wolfgang Thaller useful:

  Yes, formal protocols. Luckily, they're very rarely used in
  Cocoa.  It's only an ifgen issue; the current ifgen just
  generates ID for all id<Foo> types.  For id<Foo,Bar> used as
  a parameter, it should generate (Foo (ID a), Bar (ID a)) => ID
  a.  For return values id<Foo,Bar>, we'll have to define
  a special type ID_Bar_Foo and declare instances for Foo and Bar
  for it. The only difficult part should be to avoid defining
  those types too often...

Categories

This section is not written yet: please write to the hoc-users mailing list (see http://hoc.sourceforge.net/support.html) for assistance or, have a look at the HOC source code yourself.

Specific Classes

NSString vs. String

HOC provides the two functions toNSString :: String -> NSString (), and fromNSString :: NSString () -> String, to convert to and from Haskell strings and the Foundation framework's NSString objects.

Note that fromNSString is a pure function, and that it will not accept a subclass of NSString as an argument, because subclasses may be mutable. Make sure you never pass a casted NSMutableString to fromNSString.

If you want to work with (potentially) mutable string objects, you can use the functions haskellString :: NSString a -> IO String and stringWithHaskellString :: String -> NSStringClass a -> IO (NSString a). Use them as if they were Objective-C methods in the NSString class.

Object Messaging

Sending Messages to Objects

The Objective-C syntax [receiver method:arg1 with:arg2] that is used to send a message to a receiving object, is translated to Haskell as methodWith arg1 arg2 receiver.

The receiving object goes last in the parameter last, because then you can use ye olde trick of defining an infix function ``x # f = f x'' to produce the more object-oriented-looking code receiver # methodWith arg1 arg2. (The # infix function is defined for you by HOC already, so you don't need to define it yourself).

Note that sending messages is an IO operation, so you'll need to be in the IO monad to use it. Purely functional (non-mutable) objects such as an NSArray or a NSString provide their own specialised non-IO functions, which can be used outside of monadic code. See their documentation (or source code implementation) for details.

Message Chaining

Message chaining is a very common phenomenon in Objective-C: syntactically, it looks like [[NSCountedSet alloc] initWithArray:args]. You first send an alloc message to the NSCountedSet (class) object, and then send initWithArray:args to the result of that.

Experienced Haskell programmers will realise that this is analagous to the monadic bind operator, >>=, so the above message chain could be written as _NSCountedSet # alloc >>= initWithArray args.

Ambiguous Function Names

Some functions have the same name and are defined in more than one class: e.g. the NSProcessInfo, NSScriptCommand and NSTask classes all define a method named arguments. Any such multiply-occuring method names are not exported from the top-level framework module (Foundation or AppKit) by default: you will need to import the class specifically, e.g. import Foundation.NSProcessInfo to import NSProcessInfo's arguments function.

If you wish to use the arguments method from multiple classes, use the import qualified or import X as Y constructs, just as if you were importing a same-named function from different Haskell modules normally.

Selectors

An Objective-C selector name is translated to a Haskell function name as follows:

Colons (:) disappear
e.g. The Objective-C method name ``mouseDragged:'' is translated to ``mouseDragged''.

Initial lower-case characters after a colon (:) become upper-case
e.g. The Objective-C method name ``initWithURL:byReference:'' is translated to ``initWithURLByReference''.

Leading upper-case characters become lower-case
e.g. The Objective-C method name ``TIFFRepresentationUsingCompression:factor:'' is translated to ``tiffrepresentationUsingCompressionFactor''.

Use the getSelectorForName :: String -> SEL function to generate a Haskell SEL datatype from a raw Haskell string. As you can guess, the Haskell SEL type is the same as Objective-C's SEL type: it represents a selector (method name).

Note that the string you pass to getSelectorForName is the Objective-C selector name (with all the colons in the appropriate places), not the translated Haskell function name. For example, you should pass in "initWithURL:byReference:", and not "initWithURLByReference".

Foundation & AppKit Frameworks

The Haskell interfaces for the Foundation and AppKit frameworks (née Cocoa) are automatically built when you build and install HOC. To use them, simply write import Foundation, import AppKit or import Cocoa at the top of your Haskell module to import the entire framework's class hierarchy and method definitions into scope. (But, see the section on Ambiguous Function Names to see why some methods are not imported.)

To use your own, custom frameworks with HOC, see the chapter on Accessing Other Frameworks from Haskell.

Miscellanea

Autorelease Pools

Use the function withAutoreleasePool :: IO a to create an autorelease pool and run an IO action which which use the pool:

  main = do
    withAutoreleasePool main'
  
  main' = do
    args <- _NSProcessInfo # processInfo >>= arguments
    ...

Using withAutoreleasePool instead of an explict alloc and release for the pool saves you from remembering to release it: after your action has been run, the pool is automatically released.

enum Types

This section is not written yet: please write to the hoc-users mailing list (see http://hoc.sourceforge.net/support.html) for assistance or, have a look at the HOC source code yourself.

struct Types

This section is not written yet: please write to the hoc-users mailing list (see http://hoc.sourceforge.net/support.html) for assistance or, have a look at the HOC source code yourself.


Accessing Other Frameworks from Haskell

This section is not written yet: please write to the hoc-users mailing list (see http://hoc.sourceforge.net/support.html) for assistance or, have a look at the HOC source code yourself.


Creating an Objective-C Class in Haskell

As well as being able to use Objective-C classes in Haskell, HOC also enables you to create an Objective-C class in Haskell: you can subclass an existing Objective-C class, declare instance variables and methods in a class, and write code for it all in Haskell. You can even make your class the owner of an Interface Builder .nib file, and Interface Builder's outlets and actions can call methods in your class.

Programming Examples

If you're the type of person who learns best by following examples rather than reading documentation, HOC comes with two sample programs in the Samples/ directory of the HOC source code distribution:

  • Editor:
  • A simple text editor, which loads and saves files with a .hs extension. There are no fancy features in the editor, but it is a full document-based application. The HaskellDocument class included with this sample application is a subclass of NSDocument, and implements methods used by a document-based application, such as readFromFileOfType: and windowControllerDidLoadNib:.

  • Browser:
  • A simple class browser. It uses Objective-C's reflection capabilities to query the Foundation and AppKit frameworks, and displays all the Objective-C method names found, the corresponding Haskell function name, the Haskell type, and which class the method is defined in. (Note that this program might take a while to start up and will bounce in the dock for a while, because it's reading all the method names during startup.)

The Class Creation API

So, how do you create an Objective-C class in Haskell? The two main HOC functions you will require are declareClass and exportClass. Note that these functions are Template Haskell (TH) functions, so you'll need to use Template Haskell's special $(...) syntax to use them. (If you don't know what Template Haskell is, see the Template Haskell in a Nutshell appendix which gives a very quick overview about what it is.)

The declareClass Function

The declareClass function is somewhat analgagous to writing the type signature for a function: in the same way that a type signature tells the compiler that you intend to write the body of a function later in the code, declareClass tells HOC that you intend to define a class later in your code.

The type of declareClass is String -> String -> Q [Dec]. Its first argument is the name of the class that you wish to write in Haskell, and the second argument is the name of an existing Objective-C class that you want to subclass (such as NSObject or NSDocument). You must declare an existing class to subclass: you cannot currently create a new class which sits at the root of an object hierarchy (such as NSObject or NSProxy).

For example,

  $(declareClass "MyDocument" "NSDocument")

declares a new class named MyDocument which is a subclass of NSDocument. (Imaginative, huh?)

The exportClass Function

After using the declareClass Template Haskell function to declare a new Objective-C class, you can then export the actual definition of the class with the exportClass function. Here's the type of exportClass, which gives a very brief overview of how to use it:

  :: String         -- ^ Name of the class you're exporting,
                    --   e.g. "MyDocument" 
  -> String         -- ^ A prefix for function names which are
                    --   methods belonging to this class,
                    --   e.g. "md_"
  -> [ClassMember]  -- ^ A list of class members (see below for
                    --   example)
  -> Q [Dec]        -- ^ Code which produces a Haskell declaration,
                    --   which you can splice in with Template
                    --   Haskell's $(...) syntax

Here are the parameters you need to supply to exportClass in a bit more detail:

  • String
  • The name of the class you're exporting (which must match the name of a class you've declared previously with declareClass),

  • String
  • A methods prefix (string), which tells HOC what functions in the current Haskell source file are methods belonging to the exported class. HOC scans each function name in your Haskell source file: every function name which begins with the methods prefix you specify will be exported as a (class or instance) method, belonging to the exported class.

    For instance, if you declare and export a MyDocument class, a sensible methods prefix could be md_. Then, any function names which begins with md_ will be treated as a method for that MyDocument class. For example, md_windowNibName or md_windowControllerDidLoadNib would be methods of MyDocument (and thus expected to have the proper type signature for such a method), but wibble would not be.

  • [ClassMember]
  • This argument specifies what members the class should have, i.e. instance methods, class methods, instance variables, and outlets. The ClassMember data structure is defined as:
      data ClassMember = InstanceMethod SelectorInfo
                       | ClassMethod SelectorInfo
                       | Outlet String TypeQ
                       | InstanceVariable String TypeQ ExpQ

    Hopefully the type information will inform you about what arguments you need to provide to each of the data contructors to produce a ClassMember.

    Here's an example of what this particular argument might look like (taken directly from the Samples/Editor/HaskellDocument.hs file in the HOC source distribution):

      [ Outlet "textView" [t| NSTextView () |]
      , InstanceVariable "text" [t| Maybe (NSString ()) |] [| Nothing |]
      , InstanceMethod info_windowNibName
      , InstanceMethod info_writeToFileOfType
      , InstanceMethod info_readFromFileOfType
      , InstanceMethod info_windowControllerDidLoadNib
      ]

The output type of exportClass is Q [Dec], which is code that produces a Haskell declaration. You'll need to 'splice' this code into your source file, by using Template Haskell's $(...) syntax.

An Example

Putting it all together, here's a small example of how you might write a HaskellDocument class (which subclasses NSDocument) in Haskell:

  import HOC
  $(declareClass "HaskellDocument" "NSDocument")
  $(exportClass "HaskellDocument" "hd_" [
          Outlet "textView" [t| NSTextView () |],
          InstanceVariable "text" [t| Maybe (NSString ()) |] [| Nothing |],
          InstanceMethod info_windowNibName,
          InstanceMethod info_writeToFileOfType,
          InstanceMethod info_readFromFileOfType,
          InstanceMethod info_windowControllerDidLoadNib
      ])

Declaring your own Selectors

The HaskellDocument class in the above example only implemented methods whose types were already known because the selector was already defined somewhere in Cocoa. If you've used InterfaceBuilder to place a small button labelled with the Greek letter Pi in the lower-left corner of your window and connected it to a method named smallPiClicked:, then you'll need to declare that selector yourself using the declareSelector template function, which has the following type:

  :: String  -- ^ The Objective-C selector name
  -> TypeQ   -- ^ The method's type signature
  -> Q [Dec] -- ^ Code which produces a Haskell declaration

So for the smallPiClicked: selector you might write:

  $( declareSelector "smallPiClicked:" [t| forall a. ID a -> IO () |] )

The Objective-C selector name ``smallPiClicked:'' will be automatically mangled to smallPiClicked (as per the rules given in the Selectors section above). If you don't like this, you can use declareRenamedSelector instead:

  $( declareRenamedSelector "smallPiClicked:" "haskellNameForThisSelector"
                            [t| forall a. ID a -> IO () |] )

Due to a limitation of Template Haskell, you cannot put this declaration in the same module as your exportClass declaration: you'll have to put them in another module and import that module instead. (This is because identifiers declared by Template Haskell ``splices'' are not available to other splices within the same module.)


Tools

hocwrap

The hocwrap tool takes an executable and ``wraps'' it in a Mac OS X .app application bundle. You'll need to tell hocwrap where the bundle's Contents/ directory using the -c command-line parameter. hocwrap can also run the resulting application bundle using GHCi in an interactive fashion: more documentation about this will be coming in the future, but for now, check out the Browser and Editor applications' Makefiles in HOC's Samples/ directory, for an idea of how to use the GHCi interaction feature.

See hocwrap --help for the definitive reference on hocwrap.


Appendices

Building HOC

HOC is distributed as a standard UNIX tarball (.tar.bz2 file), and uses GNU autoconf for its build system. Building HOC should be a simple matter of the standard autoconf build mantra:

  ./configure
  make
  make install

See the README.txt file in the HOC distribution for the most up-to-date build information.

Building HOC from a CVS repository is only slightly more involved: see the BUILDING.CVS file in your checked out CVS directory (which is not included in proper release tarball) for more information.

Template Haskell in a Nutshell

Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated. — from the Template Haskell webpage at <http://www.haskell.org/th/>.

From a HOC user's viewpoint, Template Haskell makes lots of things possible in HOC that are not possible without it, and greatly simplifies the HOC API that you use to declare new classes. In the The Class Creation API section, the two functions declareClass and exportClass ``template'' functions were described. These are functions which have the mysterious output type Q [Dec]: to put it simply, the output of these template functions are actually Haskell code. Just as functional languages such as Haskell can treat functions as first-class entities, Template Haskell allows Haskell code to be treated as a first-class entity: you can pass code around to other functions, inspect the code, change it, and pass that new code to yet more functions. (If you're familiar with compilers, the code that's passed around is actually a data structure that represents the abstract syntax tree: you can walk the tree and add, change or remove nodes at your leisure.)

Of course, as well as manipulating code, you can also execute these first-class code thingys, which is what the odd-looking $(...) syntax does. That tells GHC to execute the code fragment inside the brackets: in Template Haskell terminology, this is called splicing in code. So, when you use template functions such as exportClass, they actually generate code based on the parameters you give it, and immediately splice the code in, writing out possibly hundreds of declarations and functions for you invisibly.

Of course, this appendix only covers Template Haskell as it applies to HOC: see the Template Haskell webpage (link given above) for more information on it, what you can do with it, and why it (and meta-programming in general) kicks ass.

History

A long time ago, in a galaxy far, far away ... err, wait, wrong chapter. Ahem.

The first development snapshot of HOC came out in January 2003, in a humble announcement to the glasgow-haskell-users mailing list by Wolfgang Thaller. While it worked, it was half of an experiment with Template Haskell, and half a proof-of-concept, rather than intending to be a proper language binding.

During HOC's development, another Haskell to Objective-C binding was being developed, named Mocha. Mocha was the result of André Pang's thesis on Binding Haskell to Object-Oriented and Component Systems <http://www.algorithm.com.au/files/reflection/reflection.pdf>, and it, like many thesis implementations, was also more of a proof-of-concept rather than a real, useful piece of software.

The authors of HOC and Mocha met at the Haskell Implementor's Meeting in Stockholm, Sweden later in 2003, and sat down to try to reconcile the two projects. HOC was a very different beast from Mocha: HOC wasn't typed at all (e.g. all Objective-C objects were represented using only the one ID type), for instance. Mocha, being the result of a thesis on integrating Haskell with object-oriented systems, was focused very much at bringing object-oriented style overloading into the Haskell world. Wolfgang Thaller did the heavy lifting and rewrote HOC from scratch using many of the ideas from Mocha and Andr´'s thesis, and the result is what you have today: a more supported, stable Objective-C binding than would be possible without both authors supporting each other.

 HOC: a Haskell to Objective-C bridge

SourceForge.net Logo