区分联合中的可变内部值

Mutable internal value in discriminated union

提问人:Sylverblack 提问时间:2/20/2022 更新时间:2/20/2022 访问量:109

问:

任务是创建一个二叉树,其节点具有一个可以是 true 或 false 的成员,以及一个应设置为 true 的方法(如果尚未设置为 true)。is_lockedlock()is_locked

我试过了这个

type BinaryTreeNode =
    | Node of BinaryTreeNode * BinaryTreeNode
    | End
    with
        let mutable internalIsLocked = false
        member this.is_locked
            with get() = internalIsLocked 
        member this.lock() = internalIsLocked <- true

但是编译器由于 AT LET 绑定而说不。This declaration element is not permitted in an augmentation

val mutable internalIsLocked : bool相反,出于同样的原因不起作用。

那么这个问题该如何解决呢? 难道不能用受歧视的工会来解决吗?

f# 可变 歧视性工会

评论

0赞 Fyodor Soikin 2/20/2022
不能在 ADT 上具有状态。请改用常规课程。或者,更好的是,不要使用可变状态。

答:

1赞 Brian Berns 2/20/2022 #1

如果确实想这样做,可以将可变状态移动到单独的类类型中,然后在可区分的联合中使用该类型:

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

请注意,我假设节点是不可锁定的。用法:End

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

但是,我不推荐它。

评论

0赞 Sylverblack 2/20/2022
谢谢你的回答。你会推荐什么?普通班级?
0赞 Brian Berns 2/20/2022
这取决于为什么需要锁定节点。一般来说,我更喜欢不可变的数据结构。
0赞 Sylverblack 2/20/2022
我应该补充一点,这个任务来自我想解决的编码面试。如果可能的话,我也会尽量避免可变性。