我正在尝试将图形公式从Python转换为F#
python“Node”类:
class Node:
""" A Node is the basic element of a graph. In its most basic form a graph is just a list of nodes. A Node is a really just a list of neighbors.
"""
def __init__(self, id, index=-1, name="anonymous"):
# This defines a list of edges to other nodes in the graph.
self.neighbors = set()
self.visited = False
self.id = id
# The index of this node within the list of nodes in the overall graph.
self.index = index
# Optional name, most usefull for debugging purposes.
self.name = name
def __lt__(self, other):
# Defines a < operator for this class, which allows for easily sorting a list of nodes.
return self.index < other.index
def __hash__(self):
return hash(self.id)
def __eq__(self, right):
return self.id == right.id
def add_neighbor(self, node):
""" Make node a neighbor if it is not alreadly. This is a hack, we should be allowing self to be a neighbor of self in some graphs. This should be enforced at the level of a graph, because that is where the type of the graph would disallow it.
"""
if (not node in self.neighbors) and (not self == node):
self.neighbors.add(node)
def remove_neighbor(self, node):
# Remove the node from the list of neighbors, effectively deleting that edge from
# the graph.
self.neighbors.remove(node)
def is_neighbor(self, node):
# Check if node is a member of neighbors.
return node in self.neighbors
到目前为止我的F#课程:
type Node<'T>= string*'T
type Edge<'T,'G> = Node<'T>*Node<'T>*'G
type Graph =
| Undirected of seq(Node*list Edge)
| Directed of seq(Node*list Edge *list Edge)
答案 0 :(得分:1)
是的,这与不变性有关。 F#的Set是一个不可变集合,它基于二进制树,支持在O(log n)时间内添加,删除和查找。
但是,因为集合是不可变的,所以add操作返回一个新的Set。
let originalSet = set [1; 2; 7]
let newSet = originalSet.Add(5)
最纯粹的功能解决方案可能是重建您的问题以完全消除可变性。这种方法可能会让您将节点类重构为不可变数据容器(没有方法),并在单独的模块中定义作用于该数据容器的函数。
module Nodes =
/// creates a new node from an old node with a supplied neighbour node added.
let addNeighbour neighbourNode node =
Node <| Set.add neighbourNode (node.Neighbours)
//Note: you'll need to replace the backwards pipe with brackets for pre-F# 4.0
有关更多示例,请参阅FSharp核心库中的不可变集合,例如List,Map等。
如果您更喜欢可变方法,则可以将neighbours
变为可变,以便在地图更改时更新或仅使用可变集合(例如System.Collections.Generic.HashSet<'T>
)。
当涉及到哈希码时,Set<'T>
实际上并没有使用它。它要求可以包含在其中的对象实现IComparable
接口。这用于生成二叉树所需的排序。看起来您的对象已经具有内置排序的概念,这种概念适合于提供此行为。