29

F# モナド内で と言うlet!と、コンパイラはそれをBindモナド ビルダーで定義したメンバーに変換します。

ここで MSDNに示されているように、次のように言うことができるQuery モナドがあることがわかりました。

query {
    for student in db.Student do
    select student
    count
}

and はselectcountたとえばQueryBuilderメンバーLinq.QueryBuilder.Selectおよびに変換されLinq.QueryBuilder.Countます。

私の質問は、このキーワードのメンバーへのマッピングは F# コンパイラに組み込まれていますか、それとも拡張可能ですか? たとえば、次のように言えますか。

FooMonadBuilder() {
    bar
}

どういうわけか、F# コンパイラにメソッドにbarマップすることを伝えFooMonadBuilder.Bar()ますか?

4

2 に答える 2

42

F# 2.0 (つまり、Visual Studio 2010) では、キーワード リストを拡張する方法はありません (Ramon の拡張以外)。ただし、F# 3.0 (Visual Sutdio 11) のクエリ メカニズムは拡張可能であり、 and のような独自のキーワードを定義できselectますcount

seq以下は、ビルダーのようなものをreverseキーワードで定義する基本的な例です。

type SeqBuilder() =
    // Standard definition for 'for' and 'yield' in sequences
    member x.For (source : seq<'T>, body : 'T -> seq<'R>) =
      seq { for v in source do yield! body v }
    member x.Yield item =
      seq { yield item }

    // Define an operation 'select' that performs projection
    [<CustomOperation("select")>]
    member x.Select (source : seq<'T>, [<ProjectionParameter>] f: 'T -> 'R) : seq<'R> =
        Seq.map f source

    // Defines an operation 'reverse' that reverses the sequence    
    [<CustomOperation("reverse", MaintainsVariableSpace = true)>]
    member x.Expand (source : seq<'T>) =
        List.ofSeq source |> List.rev

let mseq = SeqBuilder()

これがどのように機能するかの詳細はまだ文書化されていませんが、CustomOperation属性は操作を特別な構文として扱う必要があることを示しています (さまざまなプロパティを設定して動作を指定できますMaintainsVariableSpace。つまり、シーケンス内の値は変更されません)。このProjectionparameter属性は、キーワードに続く式を暗黙的に関数に変換する必要があることを指定します。

現在、mseqビルダーは と の両方selectをサポートしていreverseます。

let q = mseq { for i in 1 .. 10 do
               select (i + 100)
               reverse }
于 2012-02-14T10:28:42.837 に答える
4

短い答え:いいえ。

それをサポートするためにコンパイラを拡張しました。私のブログ記事http://ramon.org.il/wp/2011/04/taking-computation-expressions-one-step-further/を読んでいただければ幸いです。

于 2012-02-14T07:05:47.193 に答える