I really do enjoy the Vending Machine kata. I decided on the late night to revisit it.
module TempImpl (*Types*) type Product = Gum | Chips | Soda type Coin = Quarter | Dime | Nickel type Change = Change of Coin list type Transaction = | Purchased of Product * Change | Required of decimal | OutOfStock of Product (*Functions*) let priceOf = function | Gum -> 0.25m | Chips -> 0.50m | Soda -> 1.00m let valueOf = function | Quarter -> 0.25m | Dime -> 0.10m | Nickel -> 0.05m let balanceOf coins = (0.0m , coins) ||> List.fold (fun balance coin -> balance + (valueOf coin)) let remaining balance product = (priceOf product) - balance let rec getChange balance change = let rec get remaining change = if remaining >= valueOf Quarter then get (remaining - valueOf Quarter) (Quarter::change) elif remaining >= valueOf Dime then get (remaining - valueOf Dime) (Dime::change) elif remaining >= valueOf Nickel then get (remaining - valueOf Nickel) (Nickel::change) else change get balance  let select product deposited products = if not (products |> List.contains product) then OutOfStock product elif balanceOf deposited >= priceOf product then Purchased (product , Change <| getChange (balanceOf deposited - priceOf product) ) else Required (priceOf product - balanceOf deposited) (*Client*) let products = [ Gum ; Chips ; Soda ] |> select Gum [Quarter; Quarter; Quarter; Quarter]
Here’s the output:
val products : Transaction = Purchased (Gum,Change [Quarter; Quarter; Quarter])