我可以访问计算表达式的参数吗?

时间:2014-11-12 18:00:43

标签: f# monads computation-expression

是否可以在计算表达式中创建方法或独立函数,以后可以由计算表达式的一个规范方法使用?

我想要这样的事情:

type FormletBuilder(ctx : HttpContext) =

    let get_int = 
        match Int32.TryParse (ctx.Request.["foo"]) with
        | (true, n) -> Some n
        | _ -> None

    //similar definitions for get_date, get_non_empty_str, etc...

    member x.Bind (read : 'a option, f : 'a -> option 'a) =
        match read with
        | Some x -> f(x)
        | None -> None      

    member x.Return (obj) = Some obj
    member x.Zero () = None



    let person = formlet ctx {

        let! id = get_int "id"
        let! name = get_non_empty_str "fullname"

        return Person(id, name)
    }

但编译器抱怨get_int未定义。

2 个答案:

答案 0 :(得分:2)

let bindings in class definitions始终是私密的。您可以改为定义member

要获得简单的解决方案,您可以这样做:

let formlet = FormletBuilder(ctx)
let person = formlet {
    let! id = formlet.get_int "id"
    ...
}

答案 1 :(得分:1)

我现在明白你真正想要的是一个monad,工作流论证只是为了利用一些语法糖?如果是这样,您可以考虑做其他一些事情:

  1. 一直到Haskell并实现一个MaybeReader monad,这样它的may和reader部分都是明确的类型,
  2. 放糖 - 我知道你实际上并不需要任何核心构建器成员的上下文?如果是这样的话,那么首先可能没有任何事情可以成为建筑商的争论。有一个'干净'可能monad,将get_int等移动到一个合适的模块中,并让它们将HttpContext显式地作为参数。
  3. 如果您使用的是F#3.0或更高版本,则可以将get_int等定义为工作流的自定义操作,这应该可以有效地为您提供所需的语法。这是Tomas Petricek关于它的good post
  4. 合并2.和3. - 而不是大量的自定义操作,只需一个 - ask - 它将采用HttpContext -> 'a函数并对其应用ctx。实际上是一个卑鄙的读者版本。然后,您可以将get_int等移动到适当的模块中。