2016-08-02 5 views
0

Was soll ich tun, wenn ich gezwungen bin, einen Gewerkschaftsfall abzubilden, der nicht existieren sollte?Was soll ich tun, wenn ich gezwungen bin, einen Gewerkschaftsfall abzubilden, der nicht existieren sollte?

Der folgende Filter sorgt dafür, dass nur die Elemente einen speziellen Fall entsprechen, werden hinzugefügt:

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

Ich möchte, dann das gefilterte Ergebnis auf einen anderen Typ zuzuordnen:

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

Jedoch Ich bin immer noch gezwungen, mit einem Fall umzugehen, den ich in einer früheren Operation behandelt habe. Daher habe ich bereits die "zugeteilten" Fälle herausgefiltert.

Was soll ich in dieser Situation tun?

ist die komplette Funktion:

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 

Hier ist meine gesamte 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 optionsForPiece 

Hier sind meine 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 
+2

Als Randnotiz - Ihr Code neigt dazu, nach rechts abzuwandern, was es ein bisschen schwieriger zu folgen macht (es ist aber immer noch sehr sauber). Ziehen Sie in Erwägung, Zeilenumbrüche nach '=' zu verwenden, um die Einrückung des folgenden Codes zu reduzieren und die Pipe-Operatoren unter dem Anfangsargument anzuordnen; Ich habe noch nie jemanden gesehen, der sie so schreibt. – TeaDrivenDev

+2

Warum bringst du es einfach nicht zusammen und gibst Some (pos) und None zurück. Dann benutze List.choose, um die None loszuwerden. – s952163

+0

@TeaDrivenDev Ich aktualisierte das Format. Danke für die Rückmeldung. –

Antwort

1

Wie wäre es etwa so:

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 pro Kommentar des TDD:

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

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

Sie auch Option.map bei Bedarf nutzen können.

+3

Warum der "Umweg" über 'List.map', anstatt die Vergleichsfunktion direkt in' List.choose' zu ​​verwenden? – TeaDrivenDev

+0

danke. Lassen Sie mich dies auf den Mangel an Koffein schieben ... Ich werde bearbeiten – s952163

+2

Nicht im Zusammenhang mit der Antwort, aber wenn möglich behandeln die Fälle explizit (mit 'Zugewiesenen _' hier) anstelle der Platzhalter. Auf diese Weise, wenn Sie den Code umgestalten/aktualisieren und neue Fälle hinzufügen, wird der Compiler Sie vor einer neuen unbehandelten Anfrage warnen, anstatt sie lautlos zu verschlingen. – Sehnsucht

Verwandte Themen