当我被迫绘制一个不存在的工会案例时,我该怎么办?

时间:2016-08-02 01:25:32

标签: f#

当我被迫绘制一个不存在的工会案例时,我该怎么办?

以下过滤器可确保仅添加与特定案例匹配的元素:

let toAvailable = 
    (fun space -> match space with
                  | Available pos -> true
                  | _             -> false)

然后我想将过滤后的结果映射到另一种类型:

let availablePositions = 
    positions |> List.filter toAvailable
              |> List.map (fun space -> match space with
                                        | Available pos -> pos
                                        | Allocated _   -> (-1,-1)) // Should never happen

但是,我仍然被迫处理我在之前的操作中处理的案件。因此,我已经过滤掉了“已分配”的案例。

在这种情况下我该怎么做?

以下是完整的功能:

let optionsFor piece (positions:Space list) =

    let yDirection = match piece with
                     | Black _ -> -1
                     | Red   _ ->  1

    let sourceX , sourceY = 
        match piece with
        | Black (checker , pos) -> pos
        | Red   (checker , pos) -> pos

    let optionsForPiece = 
        (fun pos -> pos = ((sourceX - 1) , (sourceY + yDirection)) ||
                    pos = ((sourceX + 1) , (sourceY + yDirection)))

    let availablePositions = 
        positions |> List.filter toAvailable
                  |> List.map (fun space -> match space with
                                            | Available pos -> pos
                                            | Allocated _   -> (-1,-1)) // Should never happen

    availablePositions |> List.filter optionsForPiece

这是我的整个网域:

open NUnit.Framework
open FsUnit

(* Types *)
type Black = BlackKing | BlackSoldier
type Red =   RedKing   | RedSoldier

type Coordinate = int * int

type Piece =
    | Black of Black * Coordinate
    | Red   of Red   * Coordinate

type Space =
    | Allocated of Piece
    | Available of Coordinate

type Status =
    | BlacksTurn | RedsTurn
    | BlackWins  | RedWins

(* Functions *)
let black coordinate = Allocated (Black (BlackSoldier , coordinate))
let red   coordinate = Allocated (Red   (RedSoldier   , coordinate))

let startGame () =
    [ red (0,0);  red (2,0);  red (4,0);  red (6,0)
      red (1,1);  red (3,1);  red (5,1);  red (7,1)
      red (0,2);  red (2,2);  red (4,2);  red (6,2)

      Available (1,3); Available (3,3); Available (5,3); Available (7,3)
      Available (0,4); Available (2,4); Available (4,4); Available (6,4)

      black (1,5);  black (3,5);  black (5,5);  black (7,5)
      black (0,6);  black (2,6);  black (4,6);  black (6,6)
      black (1,7);  black (3,7);  black (5,7);  black (7,7) ] , BlacksTurn

let toAvailable = 
    (fun space -> match space with
                  | Available pos -> true
                  | _             -> false)

let available (positions:Space list) = positions |> List.filter toAvailable

let optionsFor piece (positions:Space list) =

    let yDirection = match piece with
                     | Black _ -> -1
                     | Red   _ ->  1

    let sourceX , sourceY = 
        match piece with
        | Black (checker , pos) -> pos
        | Red   (checker , pos) -> pos

    let optionsForPiece = 
        (fun pos -> pos = ((sourceX - 1) , (sourceY + yDirection)) ||
                    pos = ((sourceX + 1) , (sourceY + yDirection)))

    let availablePositions = 
        positions |> List.filter toAvailable
                  |> List.map (fun space -> match space with
                                            | Available pos -> pos
                                            | Allocated _   -> (-1,-1)) // Should never happen

    availablePositions |> List.filter optionsForPiece

以下是我的测试:

[<Test>]
let ``get avaialable positions for black soldier`` () =
    // Setup
    let piece = Black ( BlackSoldier , (1,5) )

    // Test
    let available = startGame () |> fst
                                 |> available
                                 |> optionsFor piece

    // Verify
    let northWestAvailable = available |> List.exists (fun pos -> pos = (0,4))
    let northEastAvailable = available |> List.exists (fun pos -> pos = (2,4))

    (northWestAvailable && northEastAvailable) |> should equal true

[<Test>]
let ``get avaialable positions for red soldier`` () =
    // Setup
    let piece = Red ( RedSoldier , (0,2) )

    // Test
    startGame () |> fst
                 |> available
                 |> optionsFor piece
                 |> List.exists (fun pos -> pos = (1,3))
                 |> should equal true

1 个答案:

答案 0 :(得分:1)

这样的事情怎么样:

type Red =   RedKing   | RedSoldier
type Black = BlackKing | BlackSoldier

type Coordinate = int * int

type Piece =
    | Black of Black * Coordinate
    | Red   of Red   * Coordinate

type Space =
    | Allocated of Piece
    | Available of Coordinate



let x1 = Allocated (Black (BlackKing, (5,5)))
let x2 = Available (10,10)
let x3 = Available  (20,10)

let xs = [x1;x2;x3]
根据TDD的评论

编辑

let xs' = 
    xs 
    |> List.choose (function | Available pos -> Some(pos)
                             | _             -> None)

// val xs' : Coordinate list = [(10, 10); (20, 10)]

如有必要,您还可以使用Option.map