F#中创建class或记录时的自引用

Self-reference during the creation of class or record in F#

我学习 F# 并通过解决 Advent of Code 2018 来做到这一点。对于 one task 我想写一个循环的 linked 列表:每个节点应该有 links 到下一个和上一个节点。一个节点的列表是有效的,该节点既是其自身的下一个又是其前一个。

这是我最初想出的记录:

type Node = {
    mutable Next: Node
    mutable Prev: Node
    Value: int
}

但是后来我发现我无法实例化值为0和links的初始节点本身。然后我尝试写一个class,但仍然没有写出我需要的合法构造函数。这是我的尝试:

type Node(value: int, next: Node, prev: Node) as this =
    let mutable _next = next
    let mutable _prev = prev
    let _value = value

    private new value =
        Node(value, this, this) // this line is illegal

    member this.Next
        with get() = _next
        and set(value) = _next <- value

    member this.Prev
        with get() = _prev
        and set(value) = _prev <- value

    member this.Value
        with get() = _value

    static member Initial value =
        Node(value)

这是我想要实现的 C# 等价物:

    public class Node {
        public Node Next { get; set; }
        public Node Prev { get; set; }
        public int Value { get; }

        public Node(int value, Node next, Node prev)
        {
            Value = value;
            Next = next;
            Prev = prev;
        }
        
        private Node(int value)
        {
            Value = value;
            Next = this;
            Prev = this;
        }

        public static Node Initial(int value)
        {
            return new Node(value);
        }
    }

我知道我可以将 Next 和 Prev 设为 Node option 类型,但这意味着由于语法限制而使我的代码变得更糟。 应该 是我遗漏的 F# 语法中的某些内容。尝试谷歌搜索并搜索类似的问题,但无济于事。

如何在创建记录期间将 link 设置为自身或在 F# 中设置 class?

这可以通过以下方式使用具有可变字段的记录来实现:

type Node = {
    mutable Next: Node
    mutable Prev: Node
    Value: int
}
with
static member CreateNew(value) = 
    let node = 
        {
            Next = Unchecked.defaultof<_>
            Prev = Unchecked.defaultof<_>
            Value = value
        }
    node.Next <- node
    node.Prev <- node
    node

Node.CreateNew(1)

您可以使用 Unchecked.defaultof<_> 绕过记录的正常不可空性。只需确保在 return.

之前将其设置为非空值