religion pensamiento obras leibniziano leibniz filosofica corriente f# monads computation-expression dynamic-keyword

pensamiento - F#: ¿Hay alguna forma de extender la lista de palabras clave de la mónada?



leibniz religion (2)

En F # 2.0 (que es Visual Studio 2010), no hay forma de extender la lista de palabras clave (aparte de la extensión de Ramon). Sin embargo, el mecanismo de consulta en F # 3.0 (Visual Sutdio 11) es extensible y puede definir sus propias palabras clave similares para select y count .

Aquí hay un ejemplo básico que define algo así como seq constructor con palabra clave 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()

Los detalles de cómo funciona esto aún no están documentados, pero el atributo CustomOperation dice que la operación debe tratarse como una sintaxis especial (puede establecer varias propiedades para especificar cómo se comporta - MaintainsVariableSpace significa que no cambia los valores dentro de la secuencia). El atributo Projectionparameter especifica que la expresión que sigue a la palabra clave debe convertirse implícitamente en una función.

Ahora, el constructor mseq admite tanto la select como la reverse :

let q = mseq { for i in 1 .. 10 do select (i + 100) reverse }

Dentro de una monada F #, si dices let! , el compilador lo convierte a un miembro Bind que ha definido en el generador de mónadas.

Ahora veo que hay mónadas de consulta, como se muestra aquí en MSDN , donde puede decir:

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

y la select y el count , por ejemplo, se traducirán a los miembros de Linq.QueryBuilder.Select y Linq.QueryBuilder.Count .

Mi pregunta es, ¿es este mapeo de palabras clave a miembros cableados en el compilador F #, o es extensible? Por ejemplo, ¿puedo decir algo como:

FooMonadBuilder() { bar }

y de alguna manera decirle al compilador F # que la bar asigna a un método FooMonadBuilder.Bar() ?