我有一个递归函数,可以创建如下所示的树:
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 -> unit
,而它应该是int*int -> 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)})
但我不明白为什么使用列表表达式不起作用。
我只是缺少一个yield关键字:
let visited = [for x, y in neighbors do
if not tiles.[y].[x] then
tiles.[y].[x] <- true
yield evaluate (x, y)]
这将编译并且不需要强制返回类型。
对于列表表达式,您需要将do
替换为->
- 请参阅此处 http://msdn.microsoft.com/en-us/library/dd233224.aspx
此外,在这种情况下,右侧必须具有一致的类型。 我会把它改成
[for x, y in (neighbors |> List.filter (fun (x2,y2) -> not tiles.[y2].[x2])) -> ...