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()
?
Respuesta corta: no.
He extendido el compilador para admitir eso, le invito a leer el artículo de mi blog http://ramon.org.il/wp/2011/04/taking-computation-expressions-one-step-further/