gpt4 book ai didi

f# - 在计算表达式中争论 TryWith

转载 作者:行者123 更新时间:2023-12-01 04:44:20 26 4
gpt4 key购买 nike

(未能“理解”FParsec,我听从了我在某处读到的建议,开始尝试自己编写一个小解析器。不知何故,我发现了一个尝试将其 monadify 的机会,现在我有了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) }

不知道我应该在零中返回什么,我只是输入了 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

最佳答案

with block 还应该返回计算表达式的结果。由于您想要返回 Result.Failure,因此您需要定义成员 m.ReturnFrom a = a 并使用它从 with block 中返回 Failure。在 try block 中,您还应该指定 fn 如果没有抛出则返回 Success。

let Combine2 p1 p2 fn =
fun a -> res { let! x = p1 a
let! y = p2 a
return!
try
Success(fn(x,y))
with
| ex -> Failure(ex.Message)
}

更新:

最初的实现显示的是警告,而不是错误。 with block 中的表达式未被使用,因为您从 try block 返回,因此您可以简单地添加 |> ignore。在这种情况下,如果 fn 抛出,则返回值为 m.Zero(),唯一的区别是您将得到 "hello world"而不是 ex.Message。下面举例说明。完整脚本在这里:http://dotnetfiddle.net/mFbeZg

使用 |> ignore 来消除警告的原始实现:

let Combine3 p1 p2 fn =
fun a -> res { let! x = p1 a
let! y = p2 a

try
return fn(x,y)
with
| ex -> Failure(ex.Message) |> ignore // no warning
}

运行它:

let comb2 a  =
let p1' x = Success(x)
let p2' y = Success(y)
let fn' (x,y) = 1/0 // div by zero
let func = Parser.Combine2 p1' p2' fn' a
func()

let comb3 a =
let p1' x = Success(x)
let p2' y = Success(y)
let fn' (x,y) = 1/0 // div by zero
let func = Parser.Combine3 p1' p2' fn' a
func()

let test2 = comb2 1
let test3 = comb3 1

结果:

val test2 : Result<int> = Failure "Attempted to divide by zero."
val test3 : Result<int> = Failure "hello world"

关于f# - 在计算表达式中争论 TryWith,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21801144/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com