(FParsec の 'grok' に失敗したので、どこかで読んだアドバイスに従い、自分で小さなパーサーを書き始めました。どういうわけか、それをモナド化するチャンスと思われるものを見つけましたが、今は N 個の問題があります...)
これは私の「結果」タイプです(簡略化)
type Result<'a> =
| Success of 'a
| Failure of string
これが計算式ビルダーです
type ResultBuilder() =
member m.Return a = Success(a)
member m.Bind(r,fn) =
match r with
| Success(a) -> fn a
| Failure(m) -> Failure(m)
この最初の例では、すべてが期待どおりに動作 (コンパイル) します。
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) }
私の問題はここにあります。「結合」関数で失敗をキャッチして失敗を返すことができるようにしたいのですが、「ゼロ」を定義する必要があると言われています。
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) }
Zero で何を返す必要があるのか わからないので、 を投げただけでmember m.Zero() = Failure("hello world")
、 が必要だと表示されますTryWith
。
そう:
member m.TryWith(r,fn) =
try
r()
with
| ex -> fn ex
そして今、遅延が必要なので、member m.Delay f = (fun () -> f())
.
その時点で、(上にex -> Failure
)This expression should have type 'unit', but has type 'Result<'a>'
、、、と私は腕を上げて皆さんの方を向いています...
再生用リンク: http://dotnetfiddle.net/Ho1sGS