XamarinでF#を使う方法

Xamarin Studio は F# をサポートしています…という記述があります。で、具体的にどうするのか?という記述を見かけなかったので、メモとして。

Xamarin Studio の「ツール」→「アドインマネージャ」で Gallary を開きます。

image

  • Mobile Development の F# support for Xamarin.Android development
  • Language bindings の F# Language Binding

の両方をインストールします。たぶん、Mobile のほうが Android に組み込む FSharep.Core で、Language のほうはコンパイラのほうだと思います。見ると、Lua とか D 言語とか並んでいるので、これでもプログラムが組めるのかも。

そうすると「新しいソリューション」でF#のAndroidアプリが組めるようになります。

image

テンプレートのコードも F# なので、Android も F# で組めますね。めでたしめでたし。

image

…と言いたいところなのですが、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 で「ポータブルクラスライブラリ」を作ります。

image

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# 側で使うのが面倒なんですけどね。

image

そんなわけで、F# の PCL を Android/iOS アプリが作れるようになりました。

サンプルは 以下からダウンロードできます。
http://1drv.ms/1g1WE9M

ちなみに、このソリューションを Xamarin Studio を開くと以下のようなエラーがでます。mono版の FSharp.Core を期待しているところに、MS版の FSharp.Core を入れられた訳で、仕方がないといえば仕方がないですね。

image

カテゴリー: F#, Xamarin パーマリンク