F#, Mono, and Mac OS X: Warmups
I've been meaning to try F# in earnest for some time just to keep up my programming chops. It's been so long since I programmed in a functional language, and that was Scheme 10 years ago. F# (like its uncle language Caml) is statically typed with crazy type inference, so it presents some new challenges. While I'm waiting for my copy of The Little MLer to arrive, I though I'd get F# up and running.
Since the objective is to build unused brain muscles, I figured it's no good just running F# in Visual Studio. While .NET interoperability is the reason to use F# over ML, I spend all day in Visual Studio. Well, I have a Mac and keep muttering about Mono... so it was settled. I would run F# in Mono on a Mac.
fsi.exe is the interactive interpreter I'm using for that most basic of functional "Hello World" examples:
let rec fac = function | 0 -> 1 | n -> n * fac(n-1);;
Install Mono and F#
The installation script and instructions for the 1.9 version of F# are clear and easy, and I had F# running on Mono/Mac quite quickly. (Ignore the thousands of compiler warnings. Apparently the ahead-of-time Mono compiler on the Mac is grouchy.) I installed F# to my /Applications folder. I'm new to the Mac, so perhaps this is heresy, but it seemed obvious. Mono seems to require an X Server to be running for its Windows.Forms implementation, and for some reason fsi.exe wants to use it. I was greeted immediately with
LittleMac:~ sebastian$ mono /Applications/FSharp/bin/fsi.exe MSR F# Interactive, (c) Microsoft Corporation, All Rights Reserved F# Version 18.104.22.168, compiling for .NET Framework Version v1.1.4322 > Unhandled Exception: System.TypeInitializationException: An exception was thrown by the type initializer for System.Windows.Forms.XplatUI ---> System.ArgumentNullException: Could not open display (X-Server required. Check you DISPLAY environment variable) Parameter name: Display at System.Windows.Forms.XplatUIX11.SetDisplay (IntPtr display_handle) [0x00000] at System.Windows.Forms.XplatUIX11..ctor () [0x00000] at System.Windows.Forms.XplatUIX11.GetInstance () [0x00000] at System.Windows.Forms.XplatUI..cctor () [0x00000] --- End of inner exception stack trace --- at <0x00000>
at System.Windows.Forms.Form.get_CreateParams () [0x00000] at System.Windows.Forms.Control.SizeFromClientSize (Size clientSize) [0x00000] at System.Windows.Forms.Control..ctor () [0x00000] at System.Windows.Forms.ScrollableControl..ctor () [0x00000] at System.Windows.Forms.ContainerControl..ctor () [0x00000] at System.Windows.Forms.Form..ctor () [0x00000] at Microsoft.FSharp.Compiler.Interactive.Shell+DummyForm..ctor () [0x00000] at (wrapper remoting-invoke-with-check) DummyForm:.ctor () at Microsoft.FSharp.Compiler.Interactive.Shell.main$cont@1318@1318 () [0x00000] at .Microsoft.FSharp.Compiler.Interactive.Shell._main () [0x00000] ** ERROR **: file mini.c: line 8704 (mono_get_lmf_addr): should not be reached aborting... Stacktrace: ** (process:1474): ERROR (recursed) **: file mini.c: line 8688 (mono_get_lmf): should not be reached aborting... Abort trap
Easy enough, just run fsi from an XTerm or write a quick script to set your $DISPLAY variable. I whipped up the following (talk about stretching unused muscles...) and put a symlink to it in my /usr/local/bin so the rest of the world would think "fsi" was really a well-behaved F# interpreter.
#!/bin/sh export DISPLAY=:0.0 mono /Applications/FSharp/bin/fsi.exe "$@"
(And the same for fsc.exe.) Now fsi fires up relatively well, issuing what appears to be harmless error on startup, but executing nicely thereafter.
LittleMac:~ sebastian$ fsi MSR F# Interactive, (c) Microsoft Corporation, All Rights Reserved F# Version 22.214.171.124, compiling for .NET Framework Version v1.1.4322 > Gtk not found (missing LD_LIBRARY_PATH to libgtk-x11-2.0.so.0?), using built-in colorscheme
Write some F#
Now I was ready to play. But while I was willing to leave Visual Studio, I wasn't willing to leave syntax-coloring, interactive buffers, and a text editor. So then began a quest to find a text editor on the Mac with a nice interactive buffer capability. I wanted to edit and type statements in one window, and see the results of their execution below, like I can with TOAD, DrScheme, and Emacs. I was originally drawn to TextMate, a favorite among the Ruby-slinging cool kids. While it is a snappy little editor with widespread language support, it doesn't yet appear to have the facility to execute interactive sessions like this. Yes, you can select expressions to send to scripts, but not to a co-executing interactive session. So off I want to that old standby, Emacs. The programming community in France has written a "tuareg-mode elisp package for Emacs that does all of this and more for Caml, a language very similar to F#. Work has been done to customize tuareg-mode for F#, and I followed in its footsteps. It worked!
Those unused muscles sure are sore now. Now can I get around to programming?