Reputation: 5543
Is it possible to create methods or stand-alone functions in a computation expression that can later be used by one of the canonical methods of a computation expression?
I want something like this:
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)
}
But the compiler complains that get_int
is not defined.
Upvotes: 2
Views: 201
Reputation: 13577
I understand now that what you actually want is a maybe monad, and the workflow argument is there just to make use of some syntactic sugar? If so, there are a couple other things you can consider doing:
ask
- which will take an HttpContext -> 'a
function and apply ctx
to it. Effectively a bastardized version of reader. Then you can move your get_int etc. into a proper module. Upvotes: 1
Reputation: 47914
let
bindings in class definitions are always private. You can define a member
instead.
For an easy solution, you could do:
let formlet = FormletBuilder(ctx)
let person = formlet {
let! id = formlet.get_int "id"
...
}
Upvotes: 2