Just started playing with F# and I want to create some mutable model inside my app to play with, using F# discriminated union instead of class hierarchy. However there seems no way to "downcast" a discriminated union and "match with" doesn't propagate mutability. What should I do?
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 -> ()
your problem is, that you match/deconstruct fb
into a new pattern/value x : int
(that is not the same as the f.x
at all!) which will of course be immutable (as bindings/values in F# are by default).
you probably see this much better if you don't give both (the value and the pattern) the same name:
> match fb with Foo { x = y } -> y;;
val it : int = 1
see you match x
against y
so y
will get the value of x
(but will not be mutable)
C#
let's look at what would be a similar situation in C#
assuming you have a Foo
class:
class Foo { public int x { get; set; } }
and a FooBar
base-class with
class Foo2 : FooBar
{
public Foo Value { get; }
}
(I striped the ctors because I am to lazy - you get the idea)
now you would do this:
var fb = new Foo2(new Foo(1));
var x = fb.Value.x;
x := 2;
do you think that fb.Value.x
will be 2
or 1
? ;)
use
let fb = Foo {x = 1}
do match fb with
| Foo f -> f.x <- 2
| Bar -> ()
instead - this will deconstruct f
out of fb
and then you can set the mutable record-field f.x
But I would suggest not starting to learn F# by trying out how to use mutable values - try to learn using immutability as much as you can istead :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With