2

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

我想要这样的东西:

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没有定义。

4

2 回答 2

2

let类定义中的绑定始终是私有的。你可以定义一个member来代替。

对于一个简单的解决方案,您可以这样做:

let formlet = FormletBuilder(ctx)
let person = formlet {
    let! id = formlet.get_int "id"
    ...
}
于 2014-11-12T18:03:04.703 回答
1

我现在明白你真正想要的是一个可能的单子,而工作流参数只是为了使用一些语法糖?如果是这样,您还可以考虑做其他几件事:

  1. 一直使用 Haskell 并实现一个 MaybeReader monad,以便它的 may 和 reader 部分在类型上都是明确的,
  2. 把糖收起来 - 我知道您实际上不需要任何核心构建器成员的上下文?如果是这样,那么它可能一开始就没有必要成为建造者的论据。有一个“干净”的可能 monad,将 get_int 等移动到适当的模块中,并让它们明确地将 HttpContext 作为参数。
  3. 如果您使用 F# 3.0 或更高版本,您可以将 get_int 等定义为工作流的自定义操作,这应该可以有效地为您提供您想要的良好语法。这是 Tomas Petricek的一篇很好的文章。
  4. 结合 2. 和 3. - 而不是大量的自定义操作,有一个 - ask- 它将接受一个HttpContext -> 'a函数并应用于ctx它。实际上是阅读器的混蛋版本。然后您可以将您的 get_int 等移动到适当的模块中。
于 2014-11-13T08:22:06.800 回答