Previous Up Next

2.3  The Coffee Machine

The following example is inspired from the Coffee Machine introduced by Milner in his CCS book [9].

The description is the following. The machine may serve coffee or tea. A tea costs ten cents whereas a coffee costs five. The user may enter dimes or nickels. He can select a tea, a coffee or ask for his money back.

type coin = Dime | Nickel
type drinks = Coffee | Tea
type buttons = BCoffee | BTea | BCancel


(* emits a drink if the accumulated value [v] is greater than [cost] *)
let node vend drink cost v = (o1, o2) where
  match v >= cost with
    true -> 
      do emit o1 = drink
      and o2 = v - cost
      done
  | false ->
      do o2 = v done
  end

Now we define a function which output a drink and return some money when necessary.

let node coffee coin button = (drink, return) where
  rec last v = 0
  and present
        coin(Nickel) -> 
          do v = last v + 5 done
      | coin(Dime) -> 
          do v = last v + 10 done
      | button(BCoffee) -> 
          do (drink, v) = vend Coffee 10 (last v)
          done
      | button(BTea) ->
          do (drink, v) = vend Tea 5 (last v)
          done
      | button(BCancel) ->
          do v = 0
          and emit return = last v
          done
      end

The function coffee can be also written like the following.

let node coffee coin button = (drink, return) where
  rec last v = 0
  and present
        coin(w) ->
          do match w with
               Nickel -> do v = last v + 5 done
             | Dime -> do v = last v + 10 done
             end
          done
      | button(b) ->
          do match b with
               BCoffee -> do (drink, v) = vend Coffee 10 (last v) done
             | BTea -> do (drink, v) = vend Tea 5 (last v) done
             | BCancel -> do v = 0 and emit return = last v done
             end
          done
       end

We end by adding the code for simulating the whole system.

(* producing events from the keyboard *)
let node input key = (coin, button) where
  match key with
    "N" -> do emit coin = Nickel done
  | "D" -> do emit coin = Dime done
  | "C" -> do emit button = BCoffee done
  | "T" -> do emit button = BTea done
  | "A" -> do emit button = BCancel done
  | _ -> do done
  end

(* printing things *)
let print_drink d =
  match d with 
    Coffee -> print_string "Coffee\n"
  | Tea -> print_string "Tea\n"
  end

let print_coin d =
  match d with 
    Nickel -> print_string "Nickel\n"
  | Dime -> print_string "Dime\n"
  end

let print_button d =
  match d with 
    BCoffee -> print_string "BCoffee\n"
  | BTea -> print_string "BTea\n"
  | BCancel -> print_string "BCancel\n"
  end

let node print f e =
  present
    e(x) -> f x
  | _ -> ()
  end

let node output drink return =
   print print_drink drink;
   print print_int return

let node main () =
  let key = read_line () in
  let (coin, button) = input key in
  let drink, return = coffee coin button in
  output drink return

The final application is obained by typing:

%lucyc -s main -sampling 0 coffee.ls
%ocamlc -o main coffee.ml main.ml

Previous Up Next