Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在F中创建(伪)循环判别并集#_Algorithm_F# - Fatal编程技术网

Algorithm 在F中创建(伪)循环判别并集#

Algorithm 在F中创建(伪)循环判别并集#,algorithm,f#,Algorithm,F#,我遇到了一个小问题。我写了这封信 这是假的。正确的。现在,当尝试测试一个循环时,我无法创建一个循环 显然,这是行不通的: let first = DataNode(1, DataNode(2, DataNode(3, DataNode(4, first)))) 但是我需要那种东西!你能告诉我如何创建一个吗?你不能用你定义的类型来创建它。请参阅,了解一些可行的替代方法 作为Brian解决方案的替代方案,您可以尝试以下方法: type Node = | DataNode of int * N

我遇到了一个小问题。我写了这封信

这是假的。正确的。现在,当尝试测试一个循环时,我无法创建一个循环

显然,这是行不通的:

  let first = DataNode(1, DataNode(2, DataNode(3, DataNode(4, first))))

但是我需要那种东西!你能告诉我如何创建一个吗?

你不能用你定义的类型来创建它。请参阅,了解一些可行的替代方法

作为Brian解决方案的替代方案,您可以尝试以下方法:

type Node = 
| DataNode of int * NodeRec
| LastNode of int
and NodeRec = { node : Node }

let rec cycle = DataNode(1, { node = 
                DataNode(2, { node = 
                DataNode(3, { node = 
                DataNode(4, { node = cycle}) }) }) })
这里有一个方法:

  type Node = 
  | DataNode of int * Lazy<Node>
  | LastNode of int

  let next node = match node with |DataNode(_,n) -> n.Value |LastNode(_) -> failwith "Error"

  let findCycle(first) =
      try
          let rec fc slow fast =
              match (slow,fast) with
              | LastNode(a),LastNode(b) when a=b->true
              | DataNode(a,_), DataNode(b,_) when a=b -> true
              | _ -> fc (next slow) (next <| next fast)
          fc first <| next first 
      with
      | _ -> false


  let first = DataNode(1, lazy DataNode(2, lazy DataNode(3, lazy DataNode(4, lazy LastNode(5)))))
  printfn "%A" (findCycle(first))


  let rec first2 = lazy DataNode(1, lazy DataNode(2, lazy DataNode(3, lazy DataNode(4, first2))))
  printfn "%A" (findCycle(first2.Value))
类型节点=
|int*Lazy的数据节点
|int的最后一个节点
让next node=将节点与| DataNode(|,n)->n.值| LastNode(|)->failwith“Error”匹配
让findCycle(第一个)=
尝试
让rec fc快速减速=
与…相匹配(慢,快)
|LastNode(a),当a=b->true时的LastNode(b)
|当a=b->true时,数据节点(a,u),数据节点(b,u)

|即使Brian和kvb都给出了有效的答案,我仍然觉得我需要看看是否有可能以不同的方式实现同样的事情。这段代码将为您提供一个循环结构,包装为Seq=Empty | Node of'a*Node=Empty | Node of'a*Lazy 你能告诉我怎么做吗

在F#中获得直接循环值有各种各样的方法(正如Brian和kvb所示),但我要指出的是,这很少是您真正想要的。直接循环数据结构是一个需要调试的工具,通常用于性能,因此是可变的

例如,您的循环图可以表示为:

> Map[1, 2; 2, 3; 3, 4; 4, 1];;
val it : Map<int,int> = map [(1, 2); (2, 3); (3, 4); (4, 1)]
>地图[1,2;2,3;3,4;4,1];;
valit:Map=Map[(1,2);(2,3);(3,4);(4,1)]

在F#中表示图形的惯用方法是存储一个从句柄映射到顶点的字典,如果需要,还可以存储另一个映射到边的字典。这种方法更易于调试,因为您可以通过可理解的查找表遍历间接递归,而不是试图在堆中破译图形。但是,如果您希望GC为您收集不可访问的子图,然后作为弱哈希映射的纯函数替代方案显然是计算机科学中尚未解决的问题。

我不确定您的算法是否符合您的要求-应该
findCycle(DataNode(1,DataNode(1,LastNode 2)))
真的计算为
true
?感谢您指出这一点。我对它进行了更改,以便它检查下一个节点是否相同。您是否应该使用引用等式而不是结构等式?是否有特殊原因使
first2
成为函数?您创建的似乎是一个无限列表,而使用
first2
lazy first2
代替
first2()
lazy.Create first2
将创建一个真实的循环(例如,任意距离的迭代只需要恒定的内存量).你说得对,我很匆忙地输入了这个,结果很草率;我现在就把它修好了。为什么F#在其他语言(如OCaml)允许的情况下禁止只使用联合类型的递归值呢?Jon:如果你的意思是“类型节点=int*节点的节点”这是完全有效的F#。@Jon-我不能权威地回答,但我怀疑这部分是由于CLR上的代码生成问题-递归值需要易变性来解决问题,但该值在逻辑上应该是不可变的。即使F#编译器隐藏了易变性,其他.NET语言也可以看到易变的实现潜在的原因是结构相等和比较不能很好地处理无限结构(例如,如果
x
是一个循环值,那么
x=x
将爆炸)。@thr:我指的是
let rec x=Node(3,x)之类的值定义
。在OCaml中是合法的。在F#中是非法的。@kvb:但这些理由不同样适用于工会和记录吗?
  type Node = 
  | DataNode of int * Lazy<Node>
  | LastNode of int

  let next node = match node with |DataNode(_,n) -> n.Value |LastNode(_) -> failwith "Error"

  let findCycle(first) =
      try
          let rec fc slow fast =
              match (slow,fast) with
              | LastNode(a),LastNode(b) when a=b->true
              | DataNode(a,_), DataNode(b,_) when a=b -> true
              | _ -> fc (next slow) (next <| next fast)
          fc first <| next first 
      with
      | _ -> false


  let first = DataNode(1, lazy DataNode(2, lazy DataNode(3, lazy DataNode(4, lazy LastNode(5)))))
  printfn "%A" (findCycle(first))


  let rec first2 = lazy DataNode(1, lazy DataNode(2, lazy DataNode(3, lazy DataNode(4, first2))))
  printfn "%A" (findCycle(first2.Value))
type Node<'a> = Empty | Node of 'a * Node<'a>

let cyclic (n:Node<_>) : _ = 
  let rn = ref n

  let rec next _ =
    match !rn with
    | Empty -> rn := n; next Unchecked.defaultof<_>
    | Node(v, x) -> rn := x; v

  Seq.initInfinite next

let nodes = Node(1, Node(2, Node(3, Empty)))
cyclic <| nodes |> Seq.take 40 // val it : seq<int> = seq [1; 2; 3; 1; ...]
//removes warning about x being recursive 
#nowarn "40"

type Node<'a> = Empty | Node of 'a * Lazy<Node<'a>>

let rec x = Node(1, lazy Node(2, lazy x))

let first = 
  match x with
  | Node(1, Lazy(Node(2,first))) -> first.Value
  | _ -> Empty
> Map[1, 2; 2, 3; 3, 4; 4, 1];;
val it : Map<int,int> = map [(1, 2); (2, 3); (3, 4); (4, 1)]