F# 自定义运算符报告计算表达式中的不正确用法
F# Custom Operator reporting incorrect usage in Computation Expression
我正在创建一个计算表达式 (CE) 来简化建模者的计划定义。我想定义仅在 CE 中可用的功能。在此示例中,编译器表示自定义操作 step
和 branch
使用不正确,但我不明白为什么。编译器只是说它们没有正确使用。
Note I know that I could define step
and branch
outside of the CE to accomplish this. This question is explicitly about using Custom Operators. I want to isolate this logic so that it is only available in the context of the CE.
type Step =
| Action of string
| Branch of string list list
type Plan =
{
Name : string
Steps : Step list
}
type PlanBuilder () =
member _.Yield _ =
{
Name = ""
Steps = []
}
member _.Run state = state
[<CustomOperation "name">]
member _.Name (state, name) =
{ state with Name = name }
[<CustomOperation "steps">]
member _.Steps (state, steps) =
{ state with Steps = steps }
[<CustomOperation "step">]
member _.Step (state, step) =
Action step
[<CustomOperation "branch">]
member _.Branch (state, branch) =
Branch branch
let plan = PlanBuilder ()
let x =
plan {
name "Chicken"
steps [
// The compiler reports errors for all the
// `step` and `branch` calls
step "1"
step "2"
branch [
[
step "3a"
step "4a"
]
[
step "3b"
step "4b"
]
]
step "5"
]
}
为 step
报告的错误
这是因为此时您在列表中。据我所知,CE 关键字仅在 CE 的“顶层”直接起作用。
您可以为单个步骤制作一个“子”CE,并在其中放置关键字,例如
plan {
name "Chicken"
steps [
// The compiler reports errors for all the
// `step` and `branch` calls
step { name "1" }
step { name "2" }
branch [
[
step { name "3a" }
step { name "4a" }
]
]
]
}
等等
除了 Isaac Abraham 关于创建子 CE 的建议之外,您还可以考虑废弃 steps
操作并重新定义 step
操作,如下所示:
[<CustomOperation "step">]
member _.Step (state, step) =
{ state with
Steps = state.Steps @ [ Action step ]
}
哪个可以让你这样做:
plan {
name "Chicken"
step "2"
step "3"
branch {
step "3a"
step "3b"
}
step "4"
step "5"
branch {
step "5a"
step "5b"
}
}
我正在创建一个计算表达式 (CE) 来简化建模者的计划定义。我想定义仅在 CE 中可用的功能。在此示例中,编译器表示自定义操作 step
和 branch
使用不正确,但我不明白为什么。编译器只是说它们没有正确使用。
Note I know that I could define
step
andbranch
outside of the CE to accomplish this. This question is explicitly about using Custom Operators. I want to isolate this logic so that it is only available in the context of the CE.
type Step =
| Action of string
| Branch of string list list
type Plan =
{
Name : string
Steps : Step list
}
type PlanBuilder () =
member _.Yield _ =
{
Name = ""
Steps = []
}
member _.Run state = state
[<CustomOperation "name">]
member _.Name (state, name) =
{ state with Name = name }
[<CustomOperation "steps">]
member _.Steps (state, steps) =
{ state with Steps = steps }
[<CustomOperation "step">]
member _.Step (state, step) =
Action step
[<CustomOperation "branch">]
member _.Branch (state, branch) =
Branch branch
let plan = PlanBuilder ()
let x =
plan {
name "Chicken"
steps [
// The compiler reports errors for all the
// `step` and `branch` calls
step "1"
step "2"
branch [
[
step "3a"
step "4a"
]
[
step "3b"
step "4b"
]
]
step "5"
]
}
为 step
报告的错误
这是因为此时您在列表中。据我所知,CE 关键字仅在 CE 的“顶层”直接起作用。
您可以为单个步骤制作一个“子”CE,并在其中放置关键字,例如
plan {
name "Chicken"
steps [
// The compiler reports errors for all the
// `step` and `branch` calls
step { name "1" }
step { name "2" }
branch [
[
step { name "3a" }
step { name "4a" }
]
]
]
}
等等
除了 Isaac Abraham 关于创建子 CE 的建议之外,您还可以考虑废弃 steps
操作并重新定义 step
操作,如下所示:
[<CustomOperation "step">]
member _.Step (state, step) =
{ state with
Steps = state.Steps @ [ Action step ]
}
哪个可以让你这样做:
plan {
name "Chicken"
step "2"
step "3"
branch {
step "3a"
step "3b"
}
step "4"
step "5"
branch {
step "5a"
step "5b"
}
}