Linux で F# を始める

この記事は [F# Advent Calendar 2014](http://connpass.com/event/9758/) の20日目の記事です。

最近、.NET Core がオープンソース化されたことが話題になりましたね。
それに伴って、.NET がマルチプラットフォームとなり Linux での動作も Microsoft がサポートしてくれるようになりました。
折角の機会ということで Linux に F# 環境を整えてみたのでこの記事ではインストールの手順や開発環境などを紹介したいと思います。

僕はメインの開発環境は Arch Linux なんですが、それだけを例にするのもあれなので Ubuntu 12.04 でもやってみました。(CentOS もやる予定だったのですが進捗ダメでした)

ちなみに僕はほとんど F# 書いたことない初心者です。

## Mono、F# のインストール
まずは .NET の実行環境である Mono と F# コンパイラをインストールします。
[ここ](http://fsharp.org/use/linux/)に書いてある情報を参考にしました。

### Ubuntu の場合
まず Mono のリポジトリを追加します。

```sh
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
```

Ubuntu 12.04 か 12.10 の場合は追加で下記も必要です。

```sh
echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | sudo tee -a /etc/apt/sources.list.d/mono-xamarin.list
```

`apt-get` を使ってインストールします。

```sh
sudo apt-get update
sudo apt-get install mono-complete fsharp
```

### Arch Linux の場合
`pacman` を使ってインストールします。

```sh
sudo pacman -S fsharp
```

簡単ですね。


## 動作確認をしてみる
早速 REPL を動かしてみます。

```
fsharpi

F# Interactive for F# 3.1 (Open Source Edition)
Freely distributed under the Apache 2.0 Open Source License

For help type #help;;

> printfn "hello, world";;
hello, world
val it : unit = ()
>
```

やったー動いたー！

これだけだとつまらないのでコンパイルして動かすのもやってみます。

お好きなエディタ (Vim) を開いて下記の内容を書いて保存します。ファイル名は適当に hoge.fs とでもしておきます。

```fsharp
open System

[<EntryPoint>]
let main argv =
    printfn "Hello World"
    let msg = Console.ReadLine()
    printfn "You typed: %s" msg
    0
```

コンパイル〜実行までは以下のようになります。

```sh
fsharpc hoge.fs
mono hoge.exe
```
```
Hello World
F#! F#!
You typed: F#! F#!
```

出来上がる実行ファイル (\*.exe) を `mono` コマンドに渡してあげるのがポイントですね。


## 開発環境を整える (IDE編)
どうせならリッチな開発環境も欲しいところです。
Visual Studio はさすがに Linux では動作しませんが、代わりに MonoDevelop というものがあります。

Ubuntu の場合は先ほどリポジトリを追加したので

```sh
sudo apt-get install monodevelop
```

で OK です。

Arch Linux の場合は現時点で公式リポジトリにあるのはバージョンが低いからか F# を有効にできないので AUR にあるものを取ってくるようにします。

```sh
yaourt -S monodevelop-stable
```

MonoDevelop はデフォルトでは F# の環境は入っていないのですが、メニューのツール→アドインマネージャから簡単にインストールできます。

![adin](http://i.gyazo.com/03e7b52b2a542e9802a70be96d7a9654.png)

見た感じなかなか完成度が高いっぽくて良さそうでした。
下記のように変数にマウスカーソルを重ねるとその型が表示されます。

![type](http://i.gyazo.com/63a1eb78d9b39c04b0fb3719a1f917da.png)

右クリックメニューです。定義ジャンプな参照の検索ができます。リファクタリングは名前の変更があるのですが、残念ながら現時点では正しく動作していないようです。

![cmenu](http://i.gyazo.com/6dbfe03e4ed6e847052d6e0dbb68b3ef.png)

ガッツリ F# 書くならこいつで良さそうですね。


## 開発環境を整える (テキストエディタ編)
MonoDevelop は初心者でも簡単に使えそうな雰囲気があって良いんですが、やはり使い慣れたテキストエディタで F# を書きたいですよね。

そういう用途のために [fsharpbinding](http://fsharp.github.io/fsharpbinding/) というのがあります。

[fsharp/fsharpbinding](https://github.com/fsharp/fsharpbinding)

さっきの MonoDevelop は内部的にこいつを使っているようですね。
言い換えると Emacs や Vim などからさきほどの MonoDevelop の機能が使えるということになります。
すごそう！

僕は Vim しか使えないので Vim を例にします。他のエディタ使いの人は公式ページを参考にインストールしてみてください。

まずはインストールなんですが、いきなり躓きます。
こいつ、プラグインのくせに特定のプラグインマネージャ (pathogen) の仕様に依存している...!

とりあえず、NeoBundle を使っている人は以下の手順でインストールできます。
まず、vimrc に NeoBundle の記述を追加します。

```vim
NeoBundle 'fsharp/fsharpbinding'
```

`NeoBundleInstall` した後下記のコマンドを実行します。

```sh
git clone git://github.com/fsharp/fsharpbinding
cd fsharpbinding/vim
make install
```
これで ~/.vim/bundle 以下に fsharpbinding ディレクトリができるんですが、
NeoBundle の設定で `neobundle#begin(expand('~/.vim/bundle'))` (昔だと `#begin` じゃなくて `#rc`) していればこれで完了です。
違うディレクトリを指定している人は、そこにコピーすれば良いでしょう。

言い忘れましたが実行には +python が必要です。(python は 2 でも 3 でも動作するようです)

とりあえずこれで Vim で F#! できるようになったはずです。
さっきの hoge.fs を Vim で開いてみます。

![vim](http://i.gyazo.com/1d24f29057cd8608bfe1dcb3b5b7fb69.png)

ちゃんとシンタックスハイライトされてますね。
それと `<Leader>t` で型の表示、`<Leader>d` で定義ジャンプなどもできます。
詳しくはドキュメント [README](https://github.com/fsharp/fsharpbinding/blob/master/vim/README.mkd) を読んでください。(ちなみに Vim のヘルプはありません)

(しかし、こいつ Vim プラグインとしてはとてもひどい出来で、さっきのインストールの例もそうですが他にもマッピングを変更できなかったり、filetype plugin のくせにグローバルなマッピングを定義したりと完全に Vim プラグインのお作法を無視しています。便利なだけにもったいない。時間あれば PR しようかな。)

## まとめ
Windows じゃなくても F#! F#! できる。