类定义中的
是否可以在计算表达式中创建方法或独立函数,以便稍后由计算表达式的规范方法之一使用?
我想要这样的东西:
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
没有定义。
let
绑定始终是私有的。您可以改为定义member
。
对于一个简单的解决方案,你可以做:
let formlet = FormletBuilder(ctx)
let person = formlet {
let! id = formlet.get_int "id"
...
}
我现在明白了,你实际上想要的是一个可能的monad,而工作流参数只是为了利用一些语法糖吗?如果是这样的话,你可以考虑做其他几件事:
- 一直使用Haskell,并实现MaybeReader monad,这样它的may和reader部分在类型上都是显式的
- 把糖收起来——我知道你实际上不需要任何核心构建者成员的上下文?如果是这样的话,也许它一开始就没有必要成为建筑商的争论。将"clean"(可能是monad)、move get_int等移到适当的模块中,并让它们显式地将HttpContext作为参数
- 如果您使用F#3.0或更高版本,您可以将get_int等定义为工作流的自定义操作,这将有效地为您提供所需的良好语法。这是托马斯·佩特里切克的一篇关于它的好文章
- 联合收割机2。和3.-与大量的自定义操作不同,有一个
ask
-它将接受HttpContext -> 'a
函数并将ctx
应用于它。然后,您可以将get_int等移动到适当的模块中