The following example is inspired from the Coffee Machine introduced by Milner in his CCS book .
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
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