(Having not received the "grok" FParsec, I followed the advice that I read somewhere and started writing a small parser myself. For some reason, I noticed that it seemed like an opportunity to try to monadize it, and now I have problems with N ... )
This is my "Result" type (simplified)
type Result<'a> = | Success of 'a | Failure of string
Here is the calculation expression builder
type ResultBuilder() = member m.Return a = Success(a) member m.Bind(r,fn) = match r with | Success(a) -> fn a | Failure(m) -> Failure(m)
In this first example, everything works (compiles) as expected:
module Parser = let res = ResultBuilder() let Combine p1 p2 fn = fun a -> res { let! x = p1 a let! y = p2 a return fn(x,y) }
My problem is here: I would like to catch any malfunction in the "combining" function and return the malfunction, but it says that I must define "zero".
let Combine2 p1 p2 fn = fun a -> res { let! x = p1 a let! y = p2 a try return fn(x,y) with | ex -> Failure(ex.Message) }
Having no idea what I should return to Zero, I just entered member m.Zero() = Failure("hello world") , and now it says I need TryWith .
So:
member m.TryWith(r,fn) = try r() with | ex -> fn ex
And now he wants Delay, so member m.Delay f = (fun () -> f()) .
At what point he says (in ex -> Failure ), This expression should have type 'unit', but has type 'Result<'a>' , and I throw my hands and speak to you guys ...
Link to play: http://dotnetfiddle.net/Ho1sGS