gpt4 book ai didi

f# - 任意长度嵌套元组上的优雅模式匹配

转载 作者:行者123 更新时间:2023-12-04 01:53:51 24 4
gpt4 key购买 nike

我正在用 F# 开发一个可组合的功能 UI 库,但我遇到了一种情况,我需要能够创建异构类型项目的“集合”。我不想通过诉诸动态编程并将所有内容强制转换为 obj(技术上可行,尤其是因为我正在使用 Fable 进行编译)来实现这一点。相反,我想尽可能多地保留类型安全。

我想出的解决方案是创建一个简单的自定义运算符 %%%构建元组,然后按如下方式使用它:

let x = 4 %%% "string" %%% () %%% 2.4

这会产生一个具有以下类型的值:
val x: (((int * string) * unit) * float)

结果类型看起来有点乱(特别是随着值数量的增加),但它确保了我的场景的强类型安全性,并且(理想情况下)对库的用户来说有点隐藏。

但是我试图找出一种优雅的方式来与这些嵌套的元组类型进行模式匹配,因为库用户有时需要对这些值编写函数。显然,这可以手动完成,例如,
match x with
| (((a,b),c),d) -> ...

并且编译器为 a 推断出正确的类型, b , c , 和 d .但是,我不希望用户不必担心所有这些嵌套。我希望能够做类似的事情,
match x with
| a %%% b %%% c %%% d -> ...

并让编译器弄清楚一切。有没有办法用 F# 使用事件模式(或其他一些功能)来完成类似的事情?

编辑:

我应该澄清一下,我并不是要在运行时匹配未知“arity”的元组值。我只想在编译时知道元素的数量(和类型)时执行此操作。如果我在做前者,我会采用动态方法。

现在,我已经创建了事件模式:
let (|Tuple2|) = function | (a,b)-> (a,b)
let (|Tuple3|) = function | ((a,b),c) -> (a,b,c)
let (|Tuple4|) = function | (((a,b),c),d) -> (a,b,c,d)
...

可以这样使用:
let x = 4 %%% "string" %%% () %%% 2.4
let y = match x with | Tuple4 (a,b,c,d) -> ...

这可能是可以做到的最好的,而且对用户来说真的没有那么糟糕(只需计算元组的“arity”,然后使用正确的 TupleN 模式)。然而,它仍然困扰着我,因为它看起来并不优雅。创建 x 时不必指定元素数量,为什么要在匹配时这样做?对我来说似乎不对称,但我没有找到避免它的方法。

我最初的想法在 F#(或一般的静态类型语言)中不起作用是否有更深层次的原因?是否有任何可能的功能语言?

最佳答案

看起来您正在尝试建立某种语义模型,尽管我并不完全清楚它到底是什么。

正如 John Palmer 所暗示的,在静态类型函数式编程语言中经常这样做的一种方法是定义一个类型来保存模型的异构值。在这种情况下,它可能是这样的:

type Model =
| Integer of int
| Text of string
| Nothing
| Float of float

(为含糊的命名道歉,但如上所述,我不清楚您要建模的确切内容。)

您现在可以建立这种类型的值:
let x = [Integer 4; Text "string"; Nothing; Float 2.4]

在这种情况下,类型为 xModel list .您现在有一个数据类型,您可以对其进行简单的模式匹配:
match x with
| [Integer i; Text s; Nothing; Float f] -> ...

如果你能想出比我在这里选择的更好的名字,这甚至可能使 API 变得有用和直观。

关于f# - 任意长度嵌套元组上的优雅模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38906758/

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