TypeProviderでFizzBuzzを取得可能な自然数型を生成する
コンパイル時に生成できますね、というだけの話です。
準備: FSharp.TypeProviders.StarterPackのインストール
NuGetからインストールしてください。
注意点としては、ファイルの定義順序がそのままだとコンパイルできない可能性があることでしょうか。
- ProvidedTypes.fsi
- ProvidedTypes.fs
- DebugProvidedTypes.fs
でコンパイルできるはず。
型を生成してFizzBuzzを取得できるようにする
https://github.com/pocketberserker/MLStudy/commit/9a0a2795d5f8915cab89a5badf65d3abe17b1cf1
FizzBuzzは1から100まで
と範囲が明確に決まっていますが、それでは面白くないので任意の範囲でとれるようにしましょう。
ProvidedStaticParameter
でTypeProvider利用時に引数を渡せるようになるとかなんとか。
定義したProvidedStaticParameter群はProvidedTypeDefinition#DefineStaticParameters
に渡すことで登録でき、第2引数で生成の操作を記述できます。
λ式内でやっていることは簡単です。
使う側ではlet inline dump (value: ^n) = (^n: (member FizzBuzz: string) value) |> printfn "%s"
という風に静的に解決された型パラメータを用いてFuzzBuzz
を持つ値を出力できるようにします。
足し算がしたい
https://github.com/pocketberserker/MLStudy/commit/aee21c03a3d7e804c48e9c2fc13655c459645e40
数値なのに足し算できないのはおかしい、ということで足し算できるようにします。
- 数値と型のマッピングをもっておく
- 足し算で得た数値の型が存在するなら
op_Addition
メソッドを定義、そうでないなら何もしない
こう改良することで、生成される範囲の自然数型で足し算ができます。 もちろんFizzBuzzも表示できます。
余談
ここで生成した各自然数型は共通するインターフェースを持ちません。 足し算程度ならインターフェースを用意しなくてもオーバーロードでごり押しできます。
発展
この状態ではリストを取得できません。 HListを用いれば良いはずですが、これに関しては読者の課題とします。