gpt4 book ai didi

scala - "Lifting"选项类型异常

转载 作者:行者123 更新时间:2023-12-04 02:52:54 27 4
gpt4 key购买 nike

F# 和 Scala 都是一种混合语言,通常用于将传统的面向对象代码与函数式代码联系起来。

更多属于 OO 世界的概念是异常(exception),而功能世界在许多情况下偏爱 Option 类型。为了包装依赖于异常的现有库代码 - 并使其更具功能性 - 因此我想“提升”异常抛出代码以返回一个选项类型。

在 Scala 中,有一个很好的库函数可以“捕获所有”并转换为选项。可以这样使用:

import scala.util.control.Exception._
val functionalVersion = allCatch opt myFunction

参见 In Scala, is there a pre-existing library function for converting exceptions to Options?

既然我要转向 F#,我也有同样的要求,但我似乎无法为此找到一个现有的实用函数 - 而且我自己也很难实现一个。

我可以为一个单元函数创建这样一个包装器,也就是一个 Action

let catchAll f = try Some (f()) with | _ -> None

但这里的问题是我不想首先将所有异常抛出代码包装到一个 Action 中。

例如,我想包装数组索引运算符,这样它就不会抛出。

// Wrap out-of-bounds exception with option type
let maybeGetIndex (array: int[]) (index: int) = catchAll (fun () -> array.[index])

maybeGetIndex [| 1; 2; 3 |] 10 // -> None

不过,如果能简单写一下就更好了

(catchAll a.[index])

即在计算之前将 catchAll 应用于整个表达式。(Scala 可以通过 call-by-name parameters 来实现,而 F# 似乎没有)

所以这个问题是双重的:

  1. 是否有现有的库函数将异常包装到选项中类型?
  2. 是否有一种语言功能可以让我实现是吗?

最佳答案

首先,我认为“更属于面向对象世界的概念是异常(exception)”是不正确的。异常存在于 ML 家族的许多函数式语言中,例如,OCaml 非常依赖它们,甚至将它们用于某些控制流结构。在 F# 中,情况并非如此,因为 .NET 异常有点慢,但我看到异常与面向对象/功能问题非常正交。

出于这个原因,我实际上发现异常通常比 F# 中的选项类型更可取。缺点是类型检查较少(您不知道会抛出什么),但优点是该语言为异常提供了很好的集成语言支持。如果您需要处理异常情况,那么异常是一种很好的方法!

要回答您关于语法技巧的原始问题 - 我可能会像您现有的代码那样使用一个函数,因为它是明确且易于理解的(并且大概您只需要在一些核心函数中进行异常包装你实现的)。

也就是说,您可以定义一个计算表达式构建器,将代码包装在主体中,并作为您的 catchAll 函数使用更简洁的语法:

type CatchAllBuilder() = 
member x.Delay(f) = try Some(f()) with _ -> None
member x.Return(v) = v

let catchAll = CatchAllBuilder()

这让你可以这样写:

catchAll { return Array.empty.[0] }

如前所述,我不会这样做,因为 (i) 我认为 F# 中不需要将所有异常都转换为选项,并且 (ii) 它引入了新团队成员(以及 future 的您)可能不熟悉的语法被混淆,但这可能是您可以获得的最好的语法。

[编辑:现在是一个带有 return 的工作版本 - 这有点不那么漂亮,但也许仍然有用!]

关于scala - "Lifting"选项类型异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54196564/

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