FSh*_*00b 29 monads f# dynamic-keyword computation-expression
在F#monad中,如果你说let!,编译器会将其转换为Bind你在monad构建器上定义的成员.
现在我看到有一个Query monads,如MSDN所示,你可以说:
query {
for student in db.Student do
select student
count
}
Run Code Online (Sandbox Code Playgroud)
和select和count,例如,将被翻译到QueryBuilder成员Linq.QueryBuilder.Select和Linq.QueryBuilder.Count.
我的问题是,关键字映射到成员是否已硬连接到F#编译器,还是可扩展?例如,我可以这样说:
FooMonadBuilder() {
bar
}
Run Code Online (Sandbox Code Playgroud)
并以某种方式告诉F#编译器bar映射到一个FooMonadBuilder.Bar()方法?
Tom*_*cek 41
在F#2.0(即Visual Studio 2010)中,无法扩展关键字列表(除了Ramon的扩展名).但是,F#3.0(Visual Sutdio 11)中的查询机制是可扩展的,您可以定义自己的类似于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()
Run Code Online (Sandbox Code Playgroud)
有关其工作原理的详细信息尚未记录,但该CustomOperation属性表示该操作应被视为特殊语法(您可以设置各种属性以指定其行为方式 - MaintainsVariableSpace意味着它不会更改序列内的值).该Projectionparameter属性指定关键字后面的表达式应隐式转换为函数.
现在,mseq构建器支持select和reverse:
let q = mseq { for i in 1 .. 10 do
select (i + 100)
reverse }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2424 次 |
| 最近记录: |