F#用于构建状态和延迟执行的计算表达式
我希望构建一个计算表达式,其中可以表达以下内容:F#用于构建状态和延迟执行的计算表达式,f#,computation-expression,F#,Computation Expression,我希望构建一个计算表达式,其中可以表达以下内容: let x = someComputationExpression { do! "Message 1" printfn "something 1" do! "Message 2" printfn "something 2" do! "Message 3" printfn "something 3" let lastValue = 4 do! "Message 4" // ne
let x = someComputationExpression {
do! "Message 1"
printfn "something 1"
do! "Message 2"
printfn "something 2"
do! "Message 3"
printfn "something 3"
let lastValue = 4
do! "Message 4"
// need to reference values across `do!`
printfn "something %s" lastValue
}
并且能够从x
列表中获取:
[| "Message 1"
"Message 2"
"Message 3"
"Message 4" |]
没有printfn
被调用,但是能够在以后执行它(如果有意义的话)
它不需要使用do
关键字,它可以是yield
或return
,无论它工作需要什么
换句话说,我希望能够在计算表达式中收集一些状态,并将稍后可以执行的工作(printfn
s)排队
我尝试了一些方法,但不确定是否可行。从OP问题中找出精确的解决方案有点困难。相反,我将发布一些代码,OP也许可以根据需要进行调整 我定义了Result和ResultGenerator
type Result =
| Direct of string
| Delayed of (unit -> unit)
type ResultGenerator<'T> = G of (Result list -> 'T*Result list )
为了提高可读性,我定义了延迟跟踪
函数:
let trace m : ResultGenerator<_> =
G <| fun rs ->
(), Delayed (fun () -> printfn "%s" m)::rs
let tracef fmt = kprintf trace fmt
取得了以下成果:
(123, [Direct "Hello"; Delayed <fun:trace@37-1>; Direct "There"])
(123,[直接“你好”;延迟;直接“那里”)
(延迟将在执行时打印跟踪)
希望这能为如何解决实际问题提供一些思路
完整资料来源:
open FStharp.Core.Printf
type Result =
| Direct of string
| Delayed of (unit -> unit)
type ResultGenerator<'T> = G of (Result list -> 'T*Result list )
let value v : ResultGenerator<_> =
G <| fun rs ->
v, rs
let bind (G t) uf : ResultGenerator<_> =
G <| fun rs ->
let tv, trs = t rs
let (G u) = uf tv
u trs
let combine (G t) (G u) : ResultGenerator<_> =
G <| fun rs ->
let _, trs = t rs
u trs
let direct v : ResultGenerator<_> =
G <| fun rs ->
(), Direct v::rs
let delayed d : ResultGenerator<_> =
G <| fun rs ->
(), Delayed d::rs
let trace m : ResultGenerator<_> =
G <| fun rs ->
(), Delayed (fun () -> printfn "%s" m)::rs
let tracef fmt = kprintf trace fmt
type Builder() =
class
member x.Bind (t, uf) = bind t uf
member x.Combine (t, u) = combine t u
member x.Return v = value v
member x.ReturnFrom t = t : ResultGenerator<_>
end
let run (G t) =
let v, rs = t []
v, List.rev rs
let builder = Builder ()
let test =
builder {
do! direct "Hello"
do! tracef "A trace:%s" "!"
do! direct "There"
return 123
}
[<EntryPoint>]
let main argv =
run test |> printfn "%A"
0
打开FStharp.Core.Printf
类型结果=
|字符串的直接形式
|延迟的(单位->单位)
类型ResultGenerator printfn“%s”m::rs
让tracef fmt=kprintf trace fmt
类型生成器()=
班
成员x.Bind(t,uf)=Bind t uf
成员x.联合收割机(t,u)=联合收割机tu
成员x.返回v=值v
成员x.ReturnFrom t=t:ResultGenerator
结束
让我们跑(G t)=
设v,rs=t[]
v、 List.rev rs
让builder=builder()
试一试=
建筑商{
直接说“你好”
do!tracef“A跟踪:%s”!“
做!直接“那里”
返回123
}
[]
让主argv=
运行测试|>printfn“%A”
0
我可以想出几种可能的解决方案,但您希望如何返回延迟的操作?在您的示例中,是否应该让
也延迟?延迟操作是否可以返回值,在这种情况下,以下表达式可能依赖于该值,并且CE在延迟操作执行之前无法完成。感谢响应。let
s可能会延迟。延迟的工作无法返回值。谢谢,这正是我要找的指导。我不再迷路了
(123, [Direct "Hello"; Delayed <fun:trace@37-1>; Direct "There"])
open FStharp.Core.Printf
type Result =
| Direct of string
| Delayed of (unit -> unit)
type ResultGenerator<'T> = G of (Result list -> 'T*Result list )
let value v : ResultGenerator<_> =
G <| fun rs ->
v, rs
let bind (G t) uf : ResultGenerator<_> =
G <| fun rs ->
let tv, trs = t rs
let (G u) = uf tv
u trs
let combine (G t) (G u) : ResultGenerator<_> =
G <| fun rs ->
let _, trs = t rs
u trs
let direct v : ResultGenerator<_> =
G <| fun rs ->
(), Direct v::rs
let delayed d : ResultGenerator<_> =
G <| fun rs ->
(), Delayed d::rs
let trace m : ResultGenerator<_> =
G <| fun rs ->
(), Delayed (fun () -> printfn "%s" m)::rs
let tracef fmt = kprintf trace fmt
type Builder() =
class
member x.Bind (t, uf) = bind t uf
member x.Combine (t, u) = combine t u
member x.Return v = value v
member x.ReturnFrom t = t : ResultGenerator<_>
end
let run (G t) =
let v, rs = t []
v, List.rev rs
let builder = Builder ()
let test =
builder {
do! direct "Hello"
do! tracef "A trace:%s" "!"
do! direct "There"
return 123
}
[<EntryPoint>]
let main argv =
run test |> printfn "%A"
0