Salsa
About
Salsa is an experimental Haskell library and code generator that allows Haskell programs to host the .NET runtime and interact with .NET libraries. It uses type families extensively to provide a type-safe mapping of the .NET object model in the Haskell type system.
Requirements
- GHC 7.8
- Salsa makes extensive use of type families and thus requires at least version 7.8 of GHC.
- Microsoft .NET Framework 3.5
- Since the Salsa code generator requires .NET 3.5, any Salsa development also requires this version. Executables produced with Salsa however will run with just .NET 2.0 (provided that only .NET 2.0 assemblies are used by the program).
- Mono support has been implemented. Salsa will be compiled against Mono if not running on windows or the flag 'use_mono' is set.
- Salsa will not work with versions 1.0/1.1 of the .NET Framework.
- Caution!
- Salsa is experimental and has not been thoroughly tested. A single typographical error can trigger multiple pages of errors from GHC, or cause it to eat lots of memory.
Getting Salsa
You can find Salsa on Hackage, but it is not getting updated frequently due to the manual build steps required. Please instead go directly to the repository on GitHub:
git clone https://github.com/tim-m89/Salsa.git
Using Salsa
Having a look at the sample programs in the Salsa distribution is probably the best way to learn how to use Salsa at the moment. There are currently three sample programs available:
- Hello: a basic console 'Hello World' program.
- Weather: a console program that asynchronously downloads the Sydney weather forecast and displays it.
- Conway: a simulator for Conway's Game of Life with a Windows Presentation Foundation GUI. (Requires .NET 3.0 or later.)
C# in Haskell
The following table shows some C# code snippets and what they translate to:
C# | Salsa | Notes |
---|---|---|
<pre-c>o.ToString()</pre-c> | o # _toString ()
|
Method names have a leading underscore and lowercase first character. |
<pre-c>Console.Write("Hi {0}!", "world");</pre-c> | _Console # _write ("Hi {0}!", "world")
|
Static methods are called similarly. |
<pre-c>Button b = new Button();</pre-c> | b <- new _Button ()
|
Constructor names have a leading underscore. |
<pre-c>s.Length</pre-c> | get s _Length
|
Use the get function to retrieve field and property values. The field/property has a leading underscore. |
<pre-c>b.Text = "OK";</pre-c> | set b [_Text := "OK"]
|
Use the set function to set the value of fields and properties. Multiple assignments can be made in the one call. |
<pre-c>b.Width = 10;</pre-c> | set b [_Width :== 10 ]
|
Use :== to assign without applying implicit conversions. This is useful for assigning polymorphic numeric literals to properties, since polymorphic-typed values confuse the Salsa coercion machinery. |
<pre-c>b.Click += (EventHandler)
delegate(...) { ... };</pre-c> |
set b [_Click :+> delegate _EventHandler (...)]
|
Use :+> to add a handler to an event, and delegate to wrap a Haskell function as a .NET delegate. |
Limitations
There are a number of .NET features that Salsa does not currently support. These include:
- generic methods and classes
- multi-dimensional arrays
- explicit coercions
- indexer properties
- exception handling
Also, only a handful of value types are automatically marshaled between Haskell and .NET (these are Int32, String, Bool and Double). All other types are marshaled by reference (which is typically what you want for .NET reference types anyway).
(Patches are certainly welcome.)
Documentation
Some of the inner workings of Salsa are described in my undergraduate thesis. In particular, Chapter 8 describes how type families are used to provide a type-safe mapping of the .NET object model in Haskell. If you're considering playing with Salsa, it is probably worth a read: