f#foldback:累加器是否需要与列表类型相同?

时间:2014-01-16 16:35:11

标签: f# fold

我有以下代码。我花了很多时间试图找出它为什么抱怨我的List.foldback函数的第二个参数。它抱怨它想要“acc”(char * bool *(Direction - > int * int)* int)。这对我没有任何意义,因为documentation表明它只是匹配'状态。在这种情况下,我试图将“状态”运动列表“。”

有关我正在做的事情的完整说明,请访问the Code golf voronoi problem

type Direction = Left=0 | Up=1 | Right=2 | Down=3
type Movement = (char * (int * int) * Direction)

let rec masterClaims (items:Movement list) =
    items

    // Execute these methods in the order in which they are passed. 
    |> List.map (fun (ch, coord, dir) -> 
        (
            ch,
            // This function does the claiming. This has to be 
            // done in the order of the input list. 
            claimCells ch coord,
            getCoordinate coord,
            int dir
        ))

    // Create next items and fold them into the final results for the layer. 
    // Use foldback so that they are pre-pended to the final list in the correct
    // order.
    |> List.foldBack (fun (ch, wasClaimed, getCoordinate, directionInt) (acc:Movement list) ->           
        if (wasClaimed) then

            // Create a list of next nodes to inspect
            // [counter-clockwise; forward; clockwise]
            [(directionInt+3)%4;directionInt;(directionInt+1)%4]
            |> List.map enum<Direction>
            |> List.iter (fun direction ->
                (
                    ch, 
                    getCoordinate direction, 
                    direction
                ) :: acc |> ignore)

        acc // should be  Movement list
        ) List.empty<Movement>


    // The theory here is that we will execute the fold
    // for every item before we pass the entire collection
    // to the recursive call. 
    |> masterClaims

Tomas'修复

的代码
let inline foldBackNormal f s input = List.foldBack f input s 

type Direction = Left=0 | Up=1 | Right=2 | Down=3
type Movement = (char * (int * int) * Direction)

let rec masterClaims (items:Movement list) =
    items

    // Execute these methods in the order in which they are passed. 
    |> List.map (fun (ch, coord, dir) -> 
        (
            ch,
            // This function does the claiming. This has to be 
            // done in the order of the input list. 
            claimCells ch coord,
            getCoordinate coord,
            int dir
        ))

    // Create next items and fold them into the final results for the layer. 
    // Use foldback so that they are pre-pended to the final list in the correct
    // order.
    |> foldBackNormal (fun (ch, wasClaimed, getCoordinate, directionInt) (acc:Movement list) ->           
        if (wasClaimed) then

            // Create a list of next nodes to inspect
            // [counter-clockwise; forward; clockwise]
            [(directionInt+3)%4;directionInt;(directionInt+1)%4]
            |> List.map enum<Direction>
            |> List.iter (fun direction ->
                (
                    ch, 
                    getCoordinate direction, 
                    direction
                ) :: acc |> ignore)

        acc // should be  Movement list
        ) List.empty<Movement>


    // The theory here is that we will execute the fold
    // for every item before we pass the entire collection
    // to the recursive call. 
    |> masterClaims

1 个答案:

答案 0 :(得分:5)

List.foldBack函数有点奇怪,它将输入列表作为参数最后一个参数之前,初始状态作为 last 参数。因此,切换最后两个参数的顺序应该可以解决问题。或者,您可以使用切换的参数顺序定义帮助程序并使用:

let foldBackNormal f s input = List.foldBack f input s

这是出于历史原因(与OCaml的兼容性),但我确信你并不是唯一一个发现这种令人困惑的人:-)。