刚刚开始玩F#,我想在我的应用程序中创建一些可变模型,使用F#discriminated union而不是类层次结构。然而似乎没有办法“低估”一个受歧视的联盟,“匹配”不会传播可变性。我该怎么办?
type Foo = {
mutable x: int
}
type FooBar =
| Foo of Foo
| Bar
let f = {x = 2};
do f.x <- 3; //All ok
let fb = Foo {x = 1}
do match fb with
| Foo {x = x} -> x <- 2 //"This value is not mutable"
| Bar -> ()
答案 0 :(得分:8)
您的问题是,您将fb
匹配/解构为新的模式/值x : int
(根本不是f.x
!),这当然是不可变的(因为F#中的绑定/值是默认值)。
> match fb with Foo { x = y } -> y;;
val it : int = 1
看到您与x
匹配y
,因此y
将获得x
的值(但不会是可变的)
C#
让我们看一下C#中的类似情况
假设您有一个Foo
类:
class Foo { public int x { get; set; } }
和FooBar
基类
class Foo2 : FooBar
{
public Foo Value { get; }
}
(因为我很懒,所以我对这些因素进行了调整 - 你得到了这个想法)
现在你会这样做:
var fb = new Foo2(new Foo(1));
var x = fb.Value.x;
x := 2;
您认为fb.Value.x
是2
还是1
? ;)
使用
let fb = Foo {x = 1}
do match fb with
| Foo f -> f.x <- 2
| Bar -> ()
相反 - 这会从f
中解构fb
,然后您可以设置可变记录字段f.x
但我建议不要通过尝试如何使用可变值来开始学习F# - 尝试尽可能多地学习使用不变性:)