3 people like it.

Another tennis implementation

Simple game of tennis... refactored after reading Richard Minerich blog post @http://richardminerich.com/2011/02/the-road-to-functional-programming-in-f-from-imperative-to-computation-expressions/

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
// This file is a script that can be executed with the F# Interactive.  
// It can be used to explore and test the library project.
// Note that script files will not be part of the project build.

type Player = A | B

type Score = 
    | Love
    | Five
    | Thirty
    | Forty

type GameState = 
    | InPlay of Score * Score
    | Duece
    | Advantage of Player
    | Won of string

type GameFunc = (GameState -> GameState)

let delay f = f()

let start = InPlay(Love,Love)

let play player state =
     let nextScore score =
         match score with
         | Love -> Five
         | Five -> Thirty
         | Thirty -> Forty
         | Forty -> Forty

     match state with
     | InPlay(p1,p2) -> 
          match player with 
          | _ when (p1 = Thirty && p2 = Forty) || (p1 = Forty && p2 = Thirty) -> Duece
          | A when p1 = Forty -> Won("Player 1")
          | B when p2 = Forty -> Won("Player 2")
          | A -> InPlay(nextScore p1, p2)
          | B -> InPlay(p1, nextScore p2)
     | Duece -> Advantage(player)
     | Advantage(p) when p = player ->  Won("Player 1")
     | Advantage(_) -> Duece  
     | _ -> state

type GameBuilder() =
    member b.Zero() = (fun _ -> start)
    member b.Yield(a : GameFunc) = a
    member b.Combine(a : GameFunc, b' : GameFunc) = a >> b'
    member b.For(vals : seq<Player>, f : Player -> GameFunc) = 
         vals |> Seq.fold (fun s n -> b.Combine(s, f n)) (b.Zero())
 
    static member Start (state : GameState) (func : GameFunc) = 
        func(state)
    
let game = GameBuilder()

let playerThatWins = [A;B;A;B;A;B;B;A;A;A] |> Seq.ofList

let result = game {
                    for playerwin in playerThatWins do 
                        yield play playerwin 
             } |> GameBuilder.Start start
union case Player.A: Player
union case Player.B: Player
type Score =
  | Love
  | Five
  | Thirty
  | Forty

Full name: Script.Score
union case Score.Love: Score
union case Score.Five: Score
union case Score.Thirty: Score
union case Score.Forty: Score
type GameState =
  | InPlay of Score * Score
  | Duece
  | Advantage of Player
  | Won of string

Full name: Script.GameState
union case GameState.InPlay: Score * Score -> GameState
union case GameState.Duece: GameState
union case GameState.Advantage: Player -> GameState
type Player =
  | A
  | B

Full name: Script.Player
union case GameState.Won: string -> GameState
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type GameFunc = GameState -> GameState

Full name: Script.GameFunc
val delay : f:(unit -> 'a) -> 'a

Full name: Script.delay
val f : (unit -> 'a)
val start : GameState

Full name: Script.start
val play : player:Player -> state:GameState -> GameState

Full name: Script.play
val player : Player
val state : GameState
val nextScore : (Score -> Score)
val score : Score
val p1 : Score
val p2 : Score
val p : Player
Multiple items
type GameBuilder =
  new : unit -> GameBuilder
  member Combine : a:GameFunc * b':GameFunc -> (GameState -> GameState)
  member For : vals:seq<Player> * f:(Player -> GameFunc) -> (GameState -> GameState)
  member Yield : a:GameFunc -> GameFunc
  member Zero : unit -> ('a -> GameState)
  static member Start : state:GameState -> func:GameFunc -> GameState

Full name: Script.GameBuilder

--------------------
new : unit -> GameBuilder
val b : GameBuilder
member GameBuilder.Zero : unit -> ('a -> GameState)

Full name: Script.GameBuilder.Zero
member GameBuilder.Yield : a:GameFunc -> GameFunc

Full name: Script.GameBuilder.Yield
val a : GameFunc
member GameBuilder.Combine : a:GameFunc * b':GameFunc -> (GameState -> GameState)

Full name: Script.GameBuilder.Combine
val b' : GameFunc
member GameBuilder.For : vals:seq<Player> * f:(Player -> GameFunc) -> (GameState -> GameState)

Full name: Script.GameBuilder.For
val vals : seq<Player>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val f : (Player -> GameFunc)
module Seq

from Microsoft.FSharp.Collections
val fold : folder:('State -> 'T -> 'State) -> state:'State -> source:seq<'T> -> 'State

Full name: Microsoft.FSharp.Collections.Seq.fold
val s : (GameState -> GameState)
val n : Player
member GameBuilder.Combine : a:GameFunc * b':GameFunc -> (GameState -> GameState)
member GameBuilder.Zero : unit -> ('a -> GameState)
static member GameBuilder.Start : state:GameState -> func:GameFunc -> GameState

Full name: Script.GameBuilder.Start
val func : GameFunc
val game : GameBuilder

Full name: Script.game
val playerThatWins : seq<Player>

Full name: Script.playerThatWins
val ofList : source:'T list -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.ofList
val result : GameState

Full name: Script.result
val playerwin : Player
static member GameBuilder.Start : state:GameState -> func:GameFunc -> GameState

More information

Link:http://fssnip.net/8Q
Posted:8 years ago
Author:Colin Bull
Tags: tennis , computational workflows