【问题标题】:What's wrong with this List expression?这个 List 表达式有什么问题?
【发布时间】:2013-12-30 02:56:53
【问题描述】:

我有一个递归函数,可以像这样创建一棵树:

let rec evaluate node = 
    let neighbors = getNeighbors node
    let visited = [for x, y in neighbors do
                       if not tiles.[y].[x] then
                           tiles.[y].[x] <- true
                           evaluate (x, y)]
    if List.length visited > 0 then 
        Node(x, y, visited) 
    else 
        Leaf(x, y)

Node 和 Leaf 来自这个定义:

type Tree =
    | Leaf of int * int
    | Node of int * int * Tree list

tiles 是一个二维布尔数组,表示已访问了哪些图块(我正在实现迷宫生成)。

现在上面的函数不能编译。推断的类型是int*int -&gt; unit,应该是int*int -&gt; Tree

我试图强制返回类型为Tree,但随后编译器抱怨调用评估的类型应为unit,但类型为Tree

我找到了一种使用序列表达式并转换为列表的解决方法:

let visited = Seq.toList (seq { 
                for x, y in neighbors do
                    if not tiles.[y].[x] then
                        tiles.[y].[x] <- true
                        yield evaluate (x, y)})

但我不明白为什么使用列表表达式不起作用。

【问题讨论】:

    标签: f#


    【解决方案1】:

    我只是缺少了一个 yield 关键字:

    let visited = [for x, y in neighbors do
                       if not tiles.[y].[x] then
                           tiles.[y].[x] <- true
                           yield evaluate (x, y)]
    

    这会编译并且不需要强制返回类型。

    【讨论】:

      【解决方案2】:

      对于列表表达式,您需要将do 替换为-&gt; - 请参阅此处http://msdn.microsoft.com/en-us/library/dd233224.aspx

      此外,在这种情况下,右侧必须具有一致的类型。我会把它改成

      [for x, y in (neighbors |> List.filter (fun (x2,y2) -> not tiles.[y2].[x2])) -> ...
      

      【讨论】:

      • 如果我这样做,我会遇到类似的错误。编译器告诉我调用评估应该返回单元但返回树,visited 被推断为单元列表而不是树列表。
      • 感谢您让我走上正轨,但要使用 if 语句,我实际上需要使用 yield
      猜你喜欢
      • 2021-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多