Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 如何定义F中自定义计算操作的收益率和#_F#_Computation Expression - Fatal编程技术网

F# 如何定义F中自定义计算操作的收益率和#

F# 如何定义F中自定义计算操作的收益率和#,f#,computation-expression,F#,Computation Expression,我正在为我的应用程序开发一些DSL,下面是我如何定义计算类型和生成器的: // expression type type Action<'a,'b> = Action of ('a -> Async<'b>) let runAction (Action r) ctx = r ctx let returnF a = Action (fun _ -> async {return a}) let bind m f = Action (fun r -> asy

我正在为我的应用程序开发一些DSL,下面是我如何定义计算类型和生成器的:

// expression type
type Action<'a,'b> = Action of ('a -> Async<'b>)

let runAction (Action r) ctx = r ctx
let returnF a = Action (fun _ -> async {return a})
let bind m f = Action (fun r -> async {
    let! a = runAction m r in return! runAction (f a) r
    })

let bindA ac f = Action (fun r -> async {
    let! a = ac in return! runAction (f a) r
    })

type ActionBuilder<'x>() =
  member this.Return(c) = returnF c
  member this.Zero()    = returnF ()
  member this.Delay(f)  = bind (returnF ()) f

  // binds both monadic and for async computations
  member this.Bind(m, f) = bind m f
  member this.Bind(m, f) = bindA m f

  member this.Combine(r1, r2) = bind r1 (fun () -> r2)
  member this.For(s:seq<_>, f)  = Action (fun x -> async {
    for i in s do runAction (f i) x |> ignore
    })

  // here's the attempt to implement 'need' operations

  [<CustomOperation("need")>]
  member this.Need(Action a,  targets: string list) =
    Action (fun x ->
      let r = a x
      printfn "need(%A, [%A])" a targets
      r)

   member this.For(a, f)  = bindA a f
   member this.Yield(()) =
    returnF ()

let action = ActionBuilder<string>()

/////////////////////////////////////////////////////////////
// other functions for Action

/// Gets action context
let getCtx = Action (fun ctx -> async {return ctx})


let needFn res = action {
    let! ctx = getCtx
    printfn "need([%A]) in %A" res ctx
  }
现在我想改变
do!needFn[“def”;“dd”]
通过定义“need”自定义操作,将语法修改为更好的语法,但会收到编译器的各种抱怨。这是正确的方法还是我误用了计算表达式


另一个问题是,如果这样做,for将不起作用!在循环体内部使用。

阅读论文后,通过尝试和错误方法,我得出了以下
实现的
Yield
builder方法不是必需的):

let forF(e:seq)prog=
使用f(e.GetEnumerator())(e->
whileF
(乐趣()->e.MoveNext())
((乐趣()->prog e.Current)|>delayF)
)
可以在中找到计算表达式生成器的完整源代码。整个项目是仿造系统的变种

注意:操作已重命名为Recipe<代码>需要
运算符根本无法实现

let program1 = fun filename -> action {
  let! a = async {return 123}
  let f = a+1

  // need ["def"; "dd"]
  do! needFn ["def"; "dd"]
  printfn "after need"

  for i in [0..10] do
    do! Async.Sleep (1)
    printfn "i: %A" i

  let! d = async {return f}
  let! ctx = getCtx
  printfn "ctx: %A, %A" ctx f
}

Async.RunSynchronously(runAction (program1 "m.c") "abc")
    let forF (e: seq<_>) prog =
    usingF (e.GetEnumerator()) (fun e ->
        whileF
            (fun () -> e.MoveNext())
            ((fun () -> prog e.Current) |> delayF)
    )