f# - 如何用循环引用声明不可变图?

标签 f# circular-reference

我想声明所有状态的图形,其中边表示连续状态。我认为我尝试做的事情可能被称为“打结”(尽管不确定)。它没有按我预期的那样工作,我有几个问题。

首先,我想要一个具有字符串名称和连续状态列表的State类型。但是此声明使编译器错误“...立即循环引用...”:

type State = string * (State list)

这种方式有效:
type State(name:string, contigs: (State list)) = 
  let name = name
  let contigs = contigs

但这实际上并不需要命名成员。一个元组很好。如何使这种简洁的语法起作用?

其次,以下代码尝试声明应该是三个连续状态的图(HI和AK是由单个节点组成的图,所有剩余状态构成最后一个图),然后是所有节点的列表。 (为简便起见,我实际上只在这里声明了少数几个州):
let rec hi = State("hi", []) 
and mo = State("mo", [il ia]) 
and il = State("il", [mo]) 
and ia = State("ia", [mo])
and states = [hi,mo,il,ia]

尽管包括“mo最终将作为其自身定义的一部分进行评估”和“表达式应具有'a->'b类型,但此处具有State类型”,但这会带来各种错误。我以为'rec'和'and'关键字可以使它起作用。我可以定义此自引用图吗?如果是这样,怎么办?

最佳答案

问题是您的数据结构和使用无效的列表元素定界符(应为分号)。这有效:(请参阅编辑)

type State =
  | State of string * State list

let rec hi = State("hi", []) 
and mo = State("mo", [il; ia]) 
and il = State("il", [mo]) 
and ia = State("ia", [mo])
let states = [hi; mo; il; ia]

递归引用将被实现为thunk(lazy)。因此,您可以通过多键入一些文字,用mutable lazy自己做同样的事情(仅供引用),您所拥有的是惯用的。

编辑

Intellisense没问题,但是编译器说

Recursive values cannot appear directly as a construction of the type 'List`1' within a recursive binding. This feature has been removed from the F# language. Consider using a record instead.



您可以通过使用seq而不是list来解决此问题。
type State =
  | State of string * State seq

let rec hi = State("hi", []) 
and mo = State("mo", seq { yield il; yield ia }) 
and il = State("il", seq { yield mo }) 
and ia = State("ia", seq { yield mo })
let states = [hi; mo; il; ia]

关于f# - 如何用循环引用声明不可变图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8761284/

相关文章:

list - 当参数为空列表时,如何避免值限制错误?

f# - 如何像 REPL 一样从 F# 打印

entity-framework - Entity Framework 报告循环引用,但没有任何意义

struct - 我使用什么生命周期来创建循环引用彼此的 Rust 结构?

F# 模式匹配一​​系列数字

asynchronous - 等待线程池中启动的异步工作流程

.net - 在纯函数设置中重用具有不同区分联合的逻辑

Java循环引用

python - 如果 __hash__ 被覆盖,Pickle/dill 无法处理循环引用

Javascript 内存泄漏 : why would assigning object to null work?