F# 自定义运算符报告计算表达式中的错误使用

Mat*_*ews 16 f# computation-expression

我正在创建一个计算表达式 (CE),以简化建模者计划的定义。我想定义仅在CE中可用的函数。在此示例中,编译器表示自定义操作stepbranch的使用不正确,但我不明白为什么。编译器所说的只是它们没有被正确使用。

请注意,我知道我可以在 CE 之外定义step和来完成此操作。branch这个问题明确是关于使用自定义运算符的。我想隔离这个逻辑,以便它仅在 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"
        ]
    }
Run Code Online (Sandbox Code Playgroud)

报告的错误step

FS3095:“步骤”使用不正确。这是此查询或计算表达式中的自定义操作。

IE:

步骤错误

Isa*_*ham 9

这是因为此时您已在列表中。据我所知,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" }
                ]
            ]
        ]
    }
Run Code Online (Sandbox Code Playgroud)

ETC。