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