F#可变匹配

4

我刚开始学习使用F#,想要在我的应用程序中创建一些可变的模型,并使用F#辨别联合代替类层次结构。然而,似乎没有办法“向下转换”一个辨别联合,并且“匹配”不会传播可变性。我该怎么办?

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 -> ()
1个回答

8

你的问题在于,你将fb匹配/解构成一个新的模式/值x:int(这与f.x完全不同!),这当然是不可变的(因为F#中的绑定/值默认情况下是不可变的)。

如果你不给两个名称相同的变量(值和模式)的话,你可能会更清楚地看到这一点:

> match fb with Foo { x = y } -> y;;
val it : int = 1

看到你在匹配xy,所以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 -> ()

相反 - 这将从fb中拆解f,然后您可以设置可变记录字段f.x

但我建议不要通过尝试使用可变值来开始学习F# - 尽可能地学习使用< strong>不可变性 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接