当我被迫绘制一个不存在的工会案例时,我该怎么办?
以下过滤器确保仅添加与特定案例匹配的元素:
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 trueWhat should I do when I'm forced to map a union case that shouldn't exist?
The following filter ensures that only elements matching a specific case are added:
let toAvailable = (fun space -> match space with | Available pos -> true | _ -> false)I then want to map the filtered result to another type:
let availablePositions = positions |> List.filter toAvailable |> List.map (fun space -> match space with | Available pos -> pos | Allocated _ -> (-1,-1)) // Should never happenHowever, I'm still forced to handle a case that I handled in a previous operation. Hence, I already filtered out the "Allocated" cases.
What should I do in this situation?
Here's the complete function:
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 optionsForPieceHere's my entire domain:
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 optionsForPieceHere are my tests:
[<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最满意答案
这样的事情怎么样:
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 。
How about something like this:
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]EDIT per TDD's comment:
let xs' = xs |> List.choose (function | Available pos -> Some(pos) | _ -> None) // val xs' : Coordinate list = [(10, 10); (20, 10)]You can also use Option.map if necessary.
更多推荐
发布评论