在 C# 中创建 F# 区分联合类型

Creating F# discrimated union type in C#

我正在尝试将 F# 项目添加到我的 C# 解决方案中。我创建了一个 F# 项目并编写了一些 F# 代码,现在我正尝试在我的 C# 项目中使用它。 我成功地引用了 F# 项目并可以访问它的类型,但在受歧视的联合方面存在问题。例如,我在 F# 中定义了以下类型:

namespace Sample

type NotificationReceiverUser = NotificationReceiverUser of string
type NotificationReceiverGroup = NotificationReceiverGroup of string
type NotificationReceiver = NotificationReceiverUser | NotificatonReceiverGroup

我可以直接创建NotificationReceiverUser对象如下:

var receiver = NotificationReceiverUser.NewNotificationReceiverUser("abc");

,但我需要 NotificationReceiver 对象,但我没有获得 NotificationReceiver.NewNotificationReceiverUser 或 NotificationReceiver.NewNotificationReceiverGroup 静态方法。查看其他一些 SO 问题,这些方法看起来应该默认可用。非常感谢任何关于为什么我缺少它们的指示。

您尝试做的不是 "discriminated union"。这是一个 不分青红皂白 的联盟。首先你创建了两种类型,然后你试图说:“第三种类型的值可能是这个或那个”。有些语言有不分青红皂白的联合(例如 TypeScript),但 F# 没有。

在 F# 中,您不能只说 "either this or that, go figure it out"。你需要给 union 的每个 case 一个 "tag"。识别它的东西。这就是为什么它被称为“discriminated”联合 - 因为您可以区分不同的情况。

例如:

type T = A of string | B of int

T 类型的值可能是 stringint,要知道哪个值是看分配给它们的 "tags" - AB

另一方面,以下在 F# 中是非法的:

type T = string | int

回到你的代码,为了"fix"它的机械方式,你需要做的就是添加区分大小写:

type NotificationReceiverUser = NotificationReceiverUser of string
type NotificationReceiverGroup = NotificationReceiverGroup of string
type NotificationReceiver = A of NotificationReceiverUser | B of NotificatonReceiverGroup

但我的直觉告诉我,你实际上想做的是:

type NotificationReceiver = 
   | NotificationReceiverUser of string 
   | NotificatonReceiverGroup of string

两个相同类型的案例(奇怪,但合法),仍然通过标签区分。

有了这样的定义,您就可以从 C# 访问它:

var receiver = NotificationReceiver.NewNotificationReceiverUser("abc");