刚开始玩 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 -> ()
最佳答案
你的问题是,你匹配/解构 fb
进入一个新的模式/值x : int
(这与 f.x
完全不同!)当然是不可变的(因为 F# 中的绑定(bind)/值是默认设置的)。
如果您不给(值和模式)都赋予相同的名称,您可能会更好地看到这一点:
> match fb with Foo { x = y } -> y;;
val it : int = 1
看你比赛
x
反对y
所以y
将得到 x
的值(但不会是可变的)C#
中的情况让我们看看 C# 中的类似情况
假设你有一个
Foo
类(class):class Foo { public int x { get; set; } }
和
FooBar
基类class Foo2 : FooBar
{
public Foo Value { get; }
}
(我删除了 ctors,因为我很懒 - 你明白了)
现在你会这样做:
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# - 尝试使用 来学习不变性尽可能多地:)
关于F# 与可变匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30627443/