F#: Is there a way to extend the monad keyword list?

前端 未结 2 1323
逝去的感伤
逝去的感伤 2021-01-30 14:11

Inside an F# monad, if you say let!, the compiler translates that to a Bind member that you\'ve defined on the monad builder.

Now I see there a

相关标签:
2条回答
  • 2021-01-30 14:29

    Short answer: no.

    I've extended the compiler to support that, you're welcome to read my blog article http://ramon.org.il/wp/2011/04/taking-computation-expressions-one-step-further/

    0 讨论(0)
  • 2021-01-30 14:39

    In F# 2.0 (that is Visual Studio 2010), there is no way to extend the keyword list (other than Ramon's extension). However, the query mechanism in F# 3.0 (Visual Sutdio 11) is extensible and you can define your own keywords similar to select and count.

    Here is a basic example that defines something like seq builder with reverse keyword:

    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()
    

    The details how this works are not yet documented, but the CustomOperation attribute says that the operation should be treated as a special syntax (you can set various properties to specify how it behaves - MaintainsVariableSpace means that it does not change the values inside sequence). The Projectionparameter attribute specifies that the expression following the keyword should be implicitly converted to a function.

    Now, the mseq builder supports both select and reverse:

    let q = mseq { for i in 1 .. 10 do
                   select (i + 100)
                   reverse }
    
    0 讨论(0)
提交回复
热议问题