F# 区分联合 - "downcasting" 到子类型
F# Discriminated Union - "downcasting" to subtype
我真的不知道这个问题的正确标题应该是什么,但是:
我在 F#
中有一个名为 MyDiscriminatedUnion
的受歧视工会:
type MyDiscriminatedUnion =
| Foo of Foo
| Bar of Bar
其中 Foo
和 Bar
是记录类型:
type Foo = {
... }
type Bar = {
... }
我创建了联合类型的值Foo
:
let foo = Foo {
... }
编译器告诉我 foo 的类型是 MyDiscriminatedUnion
.
然后我想将 foo 传递给期望类型为 Foo 的函数,而不是 MyDiscriminatedUnion
。因此编译器抱怨。我如何告诉编译器 foo
是 Foo
类型?
我试过:
let foo:Foo
构造联合类型的值时
我尝试通过以下方式"downcast" foo 到 Foo:
foo :?> MyDiscriminatedUnion.Foo
但它们都不起作用。
请帮忙。
Rubber duck debugging 这里的案例...
我需要写一个函数:
let MapToSubtype subtype =
match subtype with
| Foo foo -> foo
然后应用函数:
let x = MapToSubtype foo
...并且工作起来很有魅力。
编辑: 请注意,正如 JustSomeFSharpGuy 指出的那样,MapToSubtype
函数并未涵盖所有情况,因此编译器会发出警告,并且可能如果传入 Foo
以外的内容,则给出运行时异常。
所以函数实际上应该是这样的:
let MapToSubtype subtype =
match subtype with
| Foo foo -> foo
| _ -> // deal with exception here
这是来自 OO 语言的常见错误:此代码中不涉及子类型。将联合案例命名为与它们包含的字段类型相同的事实可能会让人感到困惑,所以让我举一个稍微不同的例子:
type MyDiscriminatedUnion =
| Its_a_Foo of Foo
| Its_a_Bar of Bar
Its_a_Foo
和 Its_a_Bar
是 不是 子类型,它们是联合案例。 MyDiscriminatedUnion
类型的值要么是 Its_a_Foo
,在这种情况下它有一个 Foo
类型的字段,要么是 Its_a_Bar
,在这种情况下它有一个类型的字段Bar
。要知道是哪一个,得到对应的字段,需要用到模式匹配。
// The function that takes a record of type Foo as argument
let f (x: Foo) = ...
// Our value of type MyDiscriminatedUnion
let myDU = Its_a_Foo { ... }
// Extracting the Foo and passing it to f
match myDU with
| Its_a_Foo foo -> f foo
| Its_a_Bar bar -> // What should we do if it's an Its_a_Bar instead?
// If you're _really_ certain that myDU is Its_a_Foo { ... }, not Its_a_Bar { ... }, you can do this.
// You will get a compile-time warning "FS0025: Incomplete pattern matches on this expression".
// If it's Its_a_Bar, you will get a runtime error.
let (Its_a_Foo foo) = myDU
f foo
我真的不知道这个问题的正确标题应该是什么,但是:
我在 F#
中有一个名为 MyDiscriminatedUnion
的受歧视工会:
type MyDiscriminatedUnion =
| Foo of Foo
| Bar of Bar
其中 Foo
和 Bar
是记录类型:
type Foo = {
... }
type Bar = {
... }
我创建了联合类型的值Foo
:
let foo = Foo {
... }
编译器告诉我 foo 的类型是 MyDiscriminatedUnion
.
然后我想将 foo 传递给期望类型为 Foo 的函数,而不是 MyDiscriminatedUnion
。因此编译器抱怨。我如何告诉编译器 foo
是 Foo
类型?
我试过:
let foo:Foo
构造联合类型的值时
我尝试通过以下方式"downcast" foo 到 Foo:
foo :?> MyDiscriminatedUnion.Foo
但它们都不起作用。
请帮忙。
Rubber duck debugging 这里的案例...
我需要写一个函数:
let MapToSubtype subtype =
match subtype with
| Foo foo -> foo
然后应用函数:
let x = MapToSubtype foo
...并且工作起来很有魅力。
编辑: 请注意,正如 JustSomeFSharpGuy 指出的那样,MapToSubtype
函数并未涵盖所有情况,因此编译器会发出警告,并且可能如果传入 Foo
以外的内容,则给出运行时异常。
所以函数实际上应该是这样的:
let MapToSubtype subtype =
match subtype with
| Foo foo -> foo
| _ -> // deal with exception here
这是来自 OO 语言的常见错误:此代码中不涉及子类型。将联合案例命名为与它们包含的字段类型相同的事实可能会让人感到困惑,所以让我举一个稍微不同的例子:
type MyDiscriminatedUnion =
| Its_a_Foo of Foo
| Its_a_Bar of Bar
Its_a_Foo
和 Its_a_Bar
是 不是 子类型,它们是联合案例。 MyDiscriminatedUnion
类型的值要么是 Its_a_Foo
,在这种情况下它有一个 Foo
类型的字段,要么是 Its_a_Bar
,在这种情况下它有一个类型的字段Bar
。要知道是哪一个,得到对应的字段,需要用到模式匹配。
// The function that takes a record of type Foo as argument
let f (x: Foo) = ...
// Our value of type MyDiscriminatedUnion
let myDU = Its_a_Foo { ... }
// Extracting the Foo and passing it to f
match myDU with
| Its_a_Foo foo -> f foo
| Its_a_Bar bar -> // What should we do if it's an Its_a_Bar instead?
// If you're _really_ certain that myDU is Its_a_Foo { ... }, not Its_a_Bar { ... }, you can do this.
// You will get a compile-time warning "FS0025: Incomplete pattern matches on this expression".
// If it's Its_a_Bar, you will get a runtime error.
let (Its_a_Foo foo) = myDU
f foo