Skip to content

Instantly share code, notes, and snippets.

@jasondown
Last active December 23, 2021 21:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jasondown/adfd9974b3a74e995fa28fe544bfb3ce to your computer and use it in GitHub Desktop.
Save jasondown/adfd9974b3a74e995fa28fe544bfb3ce to your computer and use it in GitHub Desktop.
[<AutoOpen>]
module Vending =
type internal VendingMachineMessage =
| BuyItem of custId: int
| GetStock of AsyncReplyChannel<int>
| Restock of qty: int
type VendingMachine(initialStock, output : Printer) =
let agent = MailboxProcessor<VendingMachineMessage>.Start(fun inbox ->
let rec stocked stock = async {
let! msg = inbox.Receive()
match msg with
| BuyItem id ->
let newStock = stock - 1
output.Print (sprintf $"Vend item to customer {id}\nNew stock: {newStock}")
if newStock = 0 then
return! empty()
else
return! stocked newStock
| GetStock channel ->
channel.Reply(stock)
return! stocked stock
| Restock qty ->
let newStock = stock + qty
output.Print (sprintf $"Restocking with {qty}\nCurrent stock: {newStock}")
return! stocked newStock }
and empty () = inbox.Scan(fun msg ->
match msg with
| BuyItem id ->
output.Print (sprintf $"Request for customer {id} will be fulfilled after machine is restocked")
None
| GetStock channel ->
channel.Reply(0)
Some(empty())
| Restock qty ->
output.Print (sprintf $"Restocking with {qty}\nCurrent stock: {qty}")
Some(stocked qty))
stocked initialStock)
member _.BuyItem custId = agent.Post(BuyItem custId)
member _.GetStock() = agent.PostAndReply(GetStock)
member _.Restock qty = agent.Post(Restock qty)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment