F#与mutable匹配

Dzu*_*aru 4 f#

刚刚开始玩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 -> ()
Run Code Online (Sandbox Code Playgroud)

Car*_*ten 8

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

如果你不同时给它们(值和模式)同名,你可能会看到更好的结果:

> match fb with Foo { x = y } -> y;;
val it : int = 1
Run Code Online (Sandbox Code Playgroud)

看到你匹配xy这样y会得到的值x(但不会是可变的)


的情况 C#

让我们来看看C#中会出现类似的情况

假设你有一个Foo班级:

class Foo { public int x { get; set; } }
Run Code Online (Sandbox Code Playgroud)

和一个FooBar基类

class Foo2 : FooBar 
{ 
    public Foo Value { get; } 
}
Run Code Online (Sandbox Code Playgroud)

(我把它们弄干了因为我很懒 - 你明白了)

现在你会这样做:

var fb = new Foo2(new Foo(1));
var x = fb.Value.x;
x := 2;
Run Code Online (Sandbox Code Playgroud)

你认为fb.Value.x21?;)


如何模式匹配/变异

使用

let fb = Foo {x = 1}
do match fb with
    | Foo f -> f.x <- 2
    | Bar -> ()
Run Code Online (Sandbox Code Playgroud)

相反 - 这将解构f出来fb然后你可以设置可变记录字段f.x

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