Xamarin Studio は F# をサポートしています…という記述があります。で、具体的にどうするのか?という記述を見かけなかったので、メモとして。
Xamarin Studio の「ツール」→「アドインマネージャ」で Gallary を開きます。
- Mobile Development の F# support for Xamarin.Android development
- Language bindings の F# Language Binding
の両方をインストールします。たぶん、Mobile のほうが Android に組み込む FSharep.Core で、Language のほうはコンパイラのほうだと思います。見ると、Lua とか D 言語とか並んでいるので、これでもプログラムが組めるのかも。
そうすると「新しいソリューション」でF#のAndroidアプリが組めるようになります。
テンプレートのコードも F# なので、Android も F# で組めますね。めでたしめでたし。
…と言いたいところなのですが、Xamarin の F# プロジェクトには Potral Class Library がありません。更に言うと、Xamarin が提供する FSharp.Core は Android 用のものはあるのですが、iOS 用はありません。Android 用は C:/Program Files (x86)/Reference Assemblies/Microsoft/Framework/MonoAndroid/v1.0/FSharp.Core.dll という DLL を参照していますが、iOS 版はないのです。
追記 2014/03/18
…と思ったのですが、実はあります。 monotouch のフォルダに FSharp.core がありました。なので、これをうまく使うと共有できますね。
ということは、F# で作ると、Android と Windows ストアアプリでは共有できるけど、iOS では共有できない。という結論になるのですが、ちょっと工夫すると F# のコードを Android/iOS/Windows で共有できます。
■Visual Studio で F# の PCL を作る
まずは Visual Studio で「ポータブルクラスライブラリ」を作ります。
F# で公開するクラスを使って C# で作った Android/iOS プロジェクトで参照すればよいのです。ビジネスロジックを F# で作りたい場合はこれでOKです。UI 部分も F# で作りたい場合は Xamarin Studio を使えばいいのですが、それだと iOS アプリがハブられてしまうという訳で。
ただし、ここで作った F# のコードですが、これもちょっとコツが要ります。
namespace XamarinFsLib type OreOre() = let (+++) x y = x @ y |> Seq.distinct |> Seq.toList let (---) x y = Set.intersect (Set.ofList x) (Set.ofList y) |> Set.toList member this.X = "F#" // member this.join (x, y) = x +++ y // member this.intersect (x, y) = x --- y // for C# member this.join (x:int[]) (y:int[]) = let x' = List.ofArray x let y' = List.ofArray y x' +++ y' |> List.toArray member this.intersect (x:int[]) (y:int[]) = let x' = List.ofArray x let y' = List.ofArray y x' --- y' |> List.toArray
UI用のプロジェクトで FSharp.Core を参照させてしまうと、iOS で動かなくなってしまうので、これの参照しないようにします。また、Visual Studio の PCL では、
C:/Program Files (x86)/MSBuild/../Reference Assemblies/Microsoft/FSharp/.NETCore/3.3.1.0/FSharp.Core.dll を参照しているのですが、Android のほうは
C:/Program Files (x86)/Reference Assemblies/Microsoft/Framework/MonoAndroid/v1.0/FSharp.Core.dll を参照するので、不整合が起こります。これもあって、UI 側で FSharp.Core を参照しないようにします。
先の join メソッドで List.toArray しているのは、C# 側で int[] で受け取れるからです。List を使うと F# の List が使われてしまうのでわざと int[] を使っています。こんな風にすると、UI で FSharp.Core を参照しなくて済みます。多分、Generic 関係で渡しても OK だと思います。
あと、C# の場合 join メソッドを多重化できますが、F# ではそのままではできません。なので、引数を Tuple にすればいいのですが…まあ、そうすると F# 側で使うのが面倒なんですけどね。
そんなわけで、F# の PCL を Android/iOS アプリが作れるようになりました。
サンプルは 以下からダウンロードできます。
http://1drv.ms/1g1WE9M
ちなみに、このソリューションを Xamarin Studio を開くと以下のようなエラーがでます。mono版の FSharp.Core を期待しているところに、MS版の FSharp.Core を入れられた訳で、仕方がないといえば仕方がないですね。