Yesterday I came across a handy loan payment calculator in C# by Jonathon Wood via Alvin Ashcraft’s Morning Dew links. The implementation appears to be idiomatic C# using a class, mutable properties and wrapped in a host console application to display the results.

I thought it’d be fun to spend a few moments re-implementing it in F# so it can be executed in F# interactive as a script or a console application.

Rather than use a class, I’ve plumped for a record type that captures all the required fields:

/// Loan record type Loan = { /// The total purchase price of the item being paid for. PurchasePrice : decimal /// The total down payment towards the item being purchased. DownPayment : decimal /// The annual interest rate to be charged on the loan InterestRate : double /// The term of the loan in months. This is the number of months /// that payments will be made. TermMonths : int }

And for the calculation simply a function:

/// Calculates montly payment amount let calculateMonthlyPayment (loan:Loan) = let monthsPerYear = 12 let rate = (loan.InterestRate / double monthsPerYear) / 100.0 let factor = rate + (rate / (Math.Pow(rate+1.,double loan.TermMonths) 1.)) let amount = loan.PurchasePrice - loan.DownPayment let payment = amount * decimal factor Math.Round(payment,2)

We can test the function immediately in F# interactive

let loan = { PurchasePrice = 50000M DownPayment = 0M InterestRate = 6.0 TermMonths = 5 * 12 } calculateMonthlyPayment loan

Then a test run (which produces the same results as the original code):

let displayLoanInformation (loan:Loan) = printfn "Purchase Price: %M" loan.PurchasePrice printfn "Down Payment: %M" loan.DownPayment printfn "Loan Amount: %M" (loan.PurchasePrice - loan.DownPayment) printfn "Annual Interest Rate: %f%%" loan.InterestRate printfn "Term: %d months" loan.TermMonths printfn "Monthly Payment: %f" (calculateMonthlyPayment loan) printfn "" for i in 0M .. 1000M .. 10000M do let loan = { loan with DownPayment = i } displayLoanInformation loan

Another option is to simply skip the record and use arguments:

/// Calculates montly payment amount let calculateMonthlyPayment(purchasePrice,downPayment,interestRate,months) = let monthsPerYear = 12 let rate = (interestRate / double monthsPerYear) / 100.0 let factor = rate + (rate / (Math.Pow(rate + 1.0, double months) - 1.0)) let amount = purchasePrice - downPayment let payment = amount * decimal factor Math.Round(payment,2