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