存在してはならない共用体のケースを強制的にマップするとき、どうすればよいですか?存在してはならない共用体のケースを強制的にマップするとき、どうすればよいですか?
次のフィルタは、特定の場合に一致する要素のみが追加されることを保証する。
let toAvailable =
(fun space -> match space with
| Available pos -> true
| _ -> false)
Iは、別のタイプのフィルタリングされた結果をマップする:
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
サイドノートとして、コードが右に振り回される傾向があります。これにより、コードを少し難しくしています(しかし、それはまだ非常にきれいです)。次のコードのインデントを減らし、最初の引数の下にパイプ演算子を並べるために、 '='の後に改行を使用することを検討してください。私は他の誰かがそのように書くのを見たことがない。 – TeaDrivenDev
なぜあなたはそれを崩壊させて、いくつかの(pos)とNoneを返さないのですか?その後、List.chooseを使ってNoneを取り除きます。 – s952163
@TeaDrivenDev形式を更新しました。フィードバックをお寄せいただきありがとうございます。 –