我必须编写类型为try_finalyze f g y x
的函数('a -> 'b) -> ('b -> 'c) -> 'c -> 'a -> 'c
知道:
1。如果f x
引发异常,则返回值必须为y
2。如果f x
没有引发任何异常,我们必须返回g
申请f x
的结果
exception E
let try_finalyze f g y x = try g (f x) with E -> y;;
val try_finalyze : ('a -> 'b) -> ('b -> 'c) -> 'c -> 'a -> 'c = <fun>
1.我是如何对待这个问题的?
2.在此上下文中,将执行以下功能:
fun f -> try_finalyze f (fun x-> Some x) None
我没有看到像(fun x-> Some x)
答案 0 :(得分:2)
你的第一个问题的答案是 - 不是真的。根据您的规范,函数应该捕获任何异常,而不仅仅是您的异常E
。也许我误读了,但最好使用以下定义:
let try_finalize f g y x = try g (f x) with exn -> y
至于问题的第二部分,OCaml中有几种方法可以发出错误信号。最常见的两个是:
前一个变体在语法上更轻,后者不允许调用者忽略错误条件。有时您需要从一个变体切换到另一个变体。假设您有一个引发异常的函数,并且您希望创建一个具有相同行为的函数,但返回一个选项值。让我们给它一个名字:
let with_option f = try_finalize f (fun x-> Some x) None
然后,我们可以将List.hd
转换为返回选项类型的函数,具体取决于列表是否为空:
let head x = with_option List.hd x
此函数的类型为'a list -> 'a option
,将其与List.hd
类型'a list -> 'a
进行比较,前者不允许忽略空列表情况。应用于空列表时,它将返回None
值:
# head [];;
- : 'a option = None
答案 1 :(得分:2)
如果你写
let try_finalize f g y x = try g (f x) with _ -> y
如果y
没有引发错误但f
发生错误,则您的函数将返回g
,这不是您所说的。
为了确保只捕获f
中的错误,您应该将f x
单独放在try块中:
let try_finalize f g y x =
let z = try Some (f x) with _ -> None in
match z with
| Some z -> g z
| None -> y
在纯函数代码中,异常可能被认为是错误的样式,这就是为什么你可能想要将可能引发异常的函数(例如List.assoc : 'a -> ('a * 'b) list -> 'b
)转换为执行相同操作但返回的函数的原因一个选项。
那是什么
let with_option f = try_finalize f (fun x-> Some x) None
确实
答案 2 :(得分:1)
如果我正确理解问题陈述,我想我会这样做:
let try_finalize f g y x =
try
let v = f x in g v
with _ -> y
对于问题2,假设你有一个函数f,它取v类型的值并计算r类型的结果。这个:
fun f -> try_finalize f (fun x-> Some x) None
返回尝试应用f
的函数。如果成功(即没有抛出异常),则返回Some r
。否则,它返回None
。基本上,它将一个可能将异常抛出的函数转换为一个不会抛出任何东西的函数。新函数返回r option
而不是r
。
答案 3 :(得分:0)
也许这样,但功能不再具备所需的类型
let try_finalyze f g y x = match f x with
|E -> y
| _ -> g (f x) ;;