他人様のブログを和訳・"Authoring Type Providers with the TypeProviderDSL from FSharpx"

昨日の続きを翻訳するんだ

今日もDaniel Mohl さんのブログから、2011年10月7日のエントリです

2011/10/07 FSharpx の TypeProviderDSLを用いてType Providerを生成する

数日前、私は AppSetting Type ProviderFSharpx プロジェクトに提供しました。
Fhsarpx とはコアF#ライブラリに加えて、数々の便利な「関数型構造」を追加したオープンソースのライブラリです。
チェックアウトする事を強くオススメします。


私が見た多くの便利な機能の中の一つが、TypeProviderDSL です。
これはこれは、F# 3.0 Sample Packの中で提供されるProvidedTypesモジュールにあるDSLです。
このDSLとFSharpxのいくつかのヘルパーを用いる事で、私が以前のポストでお見せしたAppSetting Type Provider はもっと読みやすくなります。
さらに、プロセスの中の何行かは削除する事が出来ます。


では、AppSettings Type Provider の中で使用する TypeProviderDSL の特徴を少しだけ見てみましょう。

1. erasedType は、ProvidedTypeDefinition を作成する単純な方法を提供してくれます。
2. staticParameter は、静的なパラメーターを定義するために必要とされるコードをカプセル化してくれます。
3. literalField は、ProvidedLiteralField を作成することをちょっとだけ簡単にしてくれます。
4. addXmlDoc は、XMLドキュメンテーションを加える共通の方法を提供してくれます。
5. 最後に、|+> オペレーターは、メンバーを加えることを非常に簡単にしてくれます。

最終結果です:
module SampleTypeProviderWithFSharxDSL

open FSharpx.TypeProviders.DSL
open Microsoft.FSharp.Core.CompilerServices
open Samples.FSharpPreviewRelease2011.ProvidedTypes
open System
open System.Configuration
open System.IO
open System.Reflection

let rootNamespace = "SampleTypeProviderWithFSharxDSL"
let thisAssembly = Assembly.GetExecutingAssembly()

let tryParseWith func = func >> function
    | true, value -> Some value
    | false, _ -> None

let (|Bool|_|) = tryParseWith Boolean.TryParse
let (|Int|_|) = tryParseWith Int32.TryParse
let (|Double|_|) = tryParseWith Double.TryParse

let addTypedAppSettings (cfg:TypeProviderConfig) (configFileName:string) (tyDef:ProvidedTypeDefinition) =
    try
        let filePath = Path.Combine(cfg.ResolutionFolder, configFileName)
        let fileMap = ExeConfigurationFileMap(ExeConfigFilename=filePath)
        let appSettings = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None).AppSettings.Settings

        Seq.iter (fun (key) ->
            tyDef
            |+> match (appSettings.Item key).Value with
                | Int fieldValue -> literalField key fieldValue
                | Bool fieldValue -> literalField key fieldValue
                | Double fieldValue -> literalField key fieldValue
                | fieldValue -> literalField key fieldValue
            |> addXmlDoc (sprintf "Returns the value from the appSetting with key %s" key)
            |> ignore) appSettings.AllKeys

        tyDef
    with
    | exn -> tyDef
    
let typedAppSettings (cfg:TypeProviderConfig) =
    erasedType<obj> thisAssembly rootNamespace "AppSettings"
      |> staticParameter "configFileName" (fun typeName configFileName ->
            erasedType<obj> thisAssembly rootNamespace typeName
                |> addTypedAppSettings cfg configFileName )

[<TypeProvider>]
type public SampleAppSettingProvider(cfg:TypeProviderConfig) as this =
    inherit TypeProviderForNamespaces()

    do this.AddNamespace(rootNamespace, [typedAppSettings cfg])

[<TypeProviderAssembly>]
do ()
FSharpx.TypeProviders は、NuGetギャラリー(http://www.nuget.org/List/Packages/FSharpx.TypeProviders)から入手出来ますし、
ソースコードGitHub(https://github.com/fsharp/fsharpx/tree/TypeProviders)にあります。 

感想


前回のコードより行数が減ってたしかに読みやすくなってますね。
FSharpx 恐ろしい子。。。
こういうオープンソースのライブラリがあるのは嬉しいし喜ばしい事なのですが、使いどころに迷いますね。
あと無いとは思いますがライブラリの乱立が起こると辟易しますね。。。