Scott Nimrod
Scott Nimrod

Reputation: 11595

What's the difference between my actual union case value and the expected value?

What's the difference between my actual union case value and the expected value?

I have the following test:

[<Test>]
let ``black checker jumps to king``() =
    let redChecker = { RedChecker.Position= { X=1 ; Y=6 } }
    let target = (redChecker, [redChecker])

    { BlackChecker.Position= { X=0 ; Y=5 } } |> jumpRed target
                                             |> fst
                                             |> should equal (BlackKing { BlackKing.Position= { X=2 ; Y=7 } })

Here's the actual result when executing the test operation in the interactive window:

val redChecker : RedChecker = {Position = {X = 1;
                                           Y = 6;};}
val target : RedChecker * RedChecker list =
  ({Position = {X = 1;
                Y = 6;};}, [{Position = {X = 1;
                                         Y = 6;};}])
val it : Checker = BlackKing {Position = {X = 2;
                                          Y = 7;};}

I see that a BlackKing value is returned with xy being (2,7). Thus, I'm verifying in my test that union case value with that specific xy value.

I'm just not seeing why my test is failing.
Any suggestions?

Appendix:

open NUnit.Framework
open FsUnit

(* Types *)
type North = NorthEast | NorthWest
type South = SouthEast | SouthWest

type Direction = 
    | NorthEast 
    | NorthWest
    | SouthEast 
    | SouthWest

type Position =     { X:int; Y:int }

type BlackChecker = { Position:Position }
type RedChecker =   { Position:Position }
type BlackKing =    { Position:Position }
type RedKing =      { Position:Position }

type Checker =
    | BlackChecker of BlackChecker
    | RedChecker   of RedChecker
    | BlackKing    of BlackKing
    | RedKing      of RedKing

type King = 
    | BlackKing of BlackKing
    | RedKing of RedKing 

(* Functions *)
let rec remove item list = list |> List.filter (fun x -> x <> item)

let setRowPosition y1 y2 y3 index =
    match index with 
    | x when x < 4 -> { X=x; Y=y1 }
    | x when x < 8 -> { X=x-4; Y=y2 }
    | _            -> { X=index-8; Y=y3 }

let initializeBlack () =
    let setPosition index =
        index |> setRowPosition 7 6 5

    let blackCheckers = List.init 12 setPosition |> List.map (fun pos -> { BlackChecker.Position= { X=pos.X; Y=pos.Y } })
    blackCheckers

let initializeRed () =
    let setPosition index =
        index |> setRowPosition 0 1 2

    let redCheckers =   List.init 12 setPosition |> List.map (fun pos -> { RedChecker.Position= { X=pos.X; Y=pos.Y } })
    redCheckers

let set (x, y) positions (position:Position) =
    match not (positions |> List.exists (fun pos -> pos = { X=x; Y=y })) with
    | true -> { X=x; Y=y }
    | false -> position

let moveBlack direction positions (checker:BlackChecker) =
    let position = checker.Position

    match direction with
    | North.NorthEast -> { BlackChecker.Position= (positions, position) ||> set ((position.X + 1), (position.Y + 1 )) } 
    | North.NorthWest -> { BlackChecker.Position= (positions, position) ||> set ((position.X - 1), (position.Y + 1 )) }

let moveRed direction positions (checker:RedChecker) =
    let position = checker.Position

    match direction with
    | South.SouthEast -> { RedChecker.Position= (positions, position) ||> set ((position.X + 1), (position.Y - 1 )) }
    | South.SouthWest -> { RedChecker.Position= (positions, position) ||> set ((position.X - 1), (position.Y - 1 )) }

let moveKing direction positions (king:King) =

    let position = match king with
                   | BlackKing bk -> bk.Position
                   | RedKing   rk -> rk.Position

    let result = match direction with
                 | NorthEast -> (positions, position) ||> set ((position.X + 1), (position.Y + 1 ))
                 | NorthWest -> (positions, position) ||> set ((position.X - 1), (position.Y + 1 ))
                 | SouthEast -> (positions, position) ||> set ((position.X + 1), (position.Y - 1 ))
                 | SouthWest -> (positions, position) ||> set ((position.X - 1), (position.Y - 1 ))

    match king with
    | BlackKing _ -> BlackKing { BlackKing.Position= result }
    | RedKing   _ -> RedKing   { RedKing.Position=   result }

let jump target yDirection source =
    let updateX value = { X=target.X + value
                          Y=target.Y + yDirection }
    match source with
    | position when position.Y + yDirection = target.Y &&
                    position.X + 1 = target.X -> updateX 1

    | position when position.Y + yDirection = target.Y &&
                    position.X - 1 = target.X -> updateX -1
    | _ -> source

let jumpRed ((redChecker:RedChecker), (redCheckers:RedChecker list)) (blackChecker:BlackChecker) =

    let yIncrementValue = 1
    let maxY = 7
    let position = blackChecker.Position |> jump redChecker.Position yIncrementValue

    match position with
    | pos when pos = blackChecker.Position -> BlackChecker { blackChecker with Position= position }, redCheckers
    | pos when pos.Y = maxY                -> Checker.BlackKing { BlackKing.Position=position }, redCheckers |> remove redChecker
    | _ -> BlackChecker { blackChecker with Position= position }, redCheckers |> remove redChecker

let jumpBlack ((blackChecker:BlackChecker),(blackCheckers:BlackChecker list))  (redChecker:RedChecker) =

    let yIncrementValue = -1
    let minY = 0
    let position = redChecker.Position |> jump blackChecker.Position yIncrementValue

    match position with
    | pos when pos = redChecker.Position -> RedChecker { redChecker with Position= position }, blackCheckers
    | pos when pos.Y = minY              -> Checker.RedKing { RedKing.Position=position }, blackCheckers |> remove blackChecker
    | _ -> RedChecker { redChecker with Position= position }, blackCheckers |> remove blackChecker

Upvotes: 0

Views: 58

Answers (1)

Ringil
Ringil

Reputation: 6527

Well this statement

{ BlackChecker.Position= { X=0 ; Y=5 } } |> jumpRed target
                                         |> fst

gives:

val it : Checker = BlackKing {Position = {X = 2;
                                      Y = 7;};}

It is of type Checker. On the other hand:

(BlackKing { BlackKing.Position= { X=2 ; Y=7 } })

gives:

val it : King = BlackKing {Position = {X = 2;
                                   Y = 7;};}

It is of type King. They aren't the same types...

If you want to compare them you need to unwrap the BlackKing type inside the things you want to compare via pattern matching.

Upvotes: 2

Related Questions