The task is to create a binary tree with its nodes having a member is_locked
that can be true or false and a method lock()
that shall set is_locked
to true if it's not already.
I tried this
type BinaryTreeNode =
| Node of BinaryTreeNode * BinaryTreeNode
| End
with
let mutable internalIsLocked = false
member this.is_locked
with get() = internalIsLocked
member this.lock() = internalIsLocked <- true
but compiler says no due to This declaration element is not permitted in an augmentation
at the let binding.
val mutable internalIsLocked : bool
instead does not work for the same reason.
How can this problem be solved then? Is it not solvable with discriminated unions?
If you really want to do this, you can move the mutable state into a separate class type, and then use that type in your discriminated union:
type Lock() =
let mutable internalIsLocked = false
member this.is_locked
with get() = internalIsLocked
member this.lock() = internalIsLocked <- true
type BinaryTreeNode =
| Node of Lock * BinaryTreeNode * BinaryTreeNode
| End
with
static member Create(left, right) =
Node (Lock(), left, right)
member this.Lock =
match this with
| Node (lock, _, _) -> Some lock
| End -> None
Note that I've assumed that End
nodes are not lockable. Usage:
let node = BinaryTreeNode.Create(End, End)
node.Lock.Value.is_locked |> printfn "%A" // false
node.Lock.Value.lock()
node.Lock.Value.is_locked |> printfn "%A" // true
However, I wouldn't recommend it.