F# 在F中创建复合迭代器#

F# 在F中创建复合迭代器#,f#,iterator,yield,c#-to-f#,lazy-sequences,F#,Iterator,Yield,C# To F#,Lazy Sequences,我正在实现一个类似跳棋的游戏,我需要一个序列来枚举给定配置的所有合法移动 我有以下函数,直接从C#翻译过来: 这是可行的,但很尴尬,而且不是“F#方式”,更不用说我有一个偷偷的怀疑,我在这里做的不是最佳性能 我想要的是将它“展平”为使用“迭代所有单元格”、“迭代所有来自此单元格的有效移动”组合的内容 以下是我希望结合的功能: let AllCells = seq { for y=0 to BOARDSIZE-1 do for x=0 to BOAR

我正在实现一个类似跳棋的游戏,我需要一个序列来枚举给定配置的所有合法移动

我有以下函数,直接从C#翻译过来:

这是可行的,但很尴尬,而且不是“F#方式”,更不用说我有一个偷偷的怀疑,我在这里做的不是最佳性能

我想要的是将它“展平”为使用“迭代所有单元格”、“迭代所有来自此单元格的有效移动”组合的内容

以下是我希望结合的功能:

let AllCells =
    seq {
        for y=0 to BOARDSIZE-1 do
            for x=0 to BOARDSIZE-1 do
                yield (x,y);
    };

让LegalMovesAround(x1,y1)=
序号{
如果电路板[x1,y1]=白色,则
对于dy=-2对2 do
对于dx=-2到2 do
设x2=x1+dx;
设y2=y1+dy;
让currentMove=newmovestruct(x1,y1,x2,y2);
如果(currentMove.DetermineMoveType MoveType.Invalical
&&板。[x2,y2]=无)然后
收益率变动;
}
我将不告诉你我的各种尝试的细节,因为它们都没有成功。但长话短说,我能想到的最好的方法是一个迭代器,该迭代器在每次生成时返回一个seq,而不是我正在寻找的平坦版本,它将返回一个简单的MoveStruct

有人知道如何组合所有单元格和LegalMovesAround(x,y)吗

问候,,
Aleks

您应该能够按原样组合它们,然后将它们展平,如下所示:

 let validMoves = 
    AllCells 
    |> Seq.collect LegalMovesAround
    |> Seq.distinct
但从性能角度来看,它可能不是最好的解决方案


编辑:根据Tomas注释修复了示例代码

您可以使用yield!在新的序列表达式中:

let allLegalMoves = seq {
  for cell in AllCells do
    yield! LegalMovesAround cell
}

您是否知道
yield

差不多

seq {
    for x,y in Allcells do
        yield! LMA(x,y)
}

小心混合惰性序列和副作用!如果电路板发生了变异,那么清楚地了解整个序列的评估时间是很重要的。调用Seq.distinct在这里看起来很危险。不要介意我上面的评论,在进入移动树之前会调用Seq.distinct。这不是类型检查。我想
legalMovesAround
应该是
Seq.collect
@Tomas的论点:我真的不应该在没有FSI的情况下写答案。:)谢谢,这正是我想要的解决方案。简而言之,直截了当地说,循环是没有的:)这个解决方案也可以工作,除了它返回一个带有每个yield的序列,而我更喜欢它返回一个MoveStruct。调用方不需要知道实现的细节。不,它会生成一个MoveStruct。试试看。
let allLegalMoves = seq {
  for cell in AllCells do
    yield! LegalMovesAround cell
}
seq {
    for x,y in Allcells do
        yield! LMA(x,y)
}