Phillip Trelford's Array

POKE 36879,255

FP Day saw talks from luminaries in the Functional Programming world, Simon Peyton-Jones and Don Syme give key notes, with hands-on tutorials and experience reports on F#, Clojure and Haskell sandwiched in the middle. Tomas Petricek and I provided the F# filling, and Zach Bray applied the F# source.

Turning to the Functional Side With F#

F# is a multi-paradigm programming language with first-class support for Functional Programming, and ships with Visual Studio 2010. Using a mixture of presentation and practical exercises this session aims to help you:

• learn how to use F#
• think in a functional way
• model problem domains using functional types

The morning tasks were based on a Point-of-sale (POS) application.

Domain Model:

```namespace Checkout

// Common types

type Code = string
type Name = string
type Price = decimal
type Product = Product of Code * Name * Price
type Quantity = decimal

/// Tender types
type Tender =
| Cash
| Card of string
| Voucher

/// Represents line item
type LineItem =
| SaleLineItem of int * Product * Quantity
| TenderLineItem of Tender * Price
| CancelLineItem of int```

Product lookup:

```[<AutoOpen>]
module Products =
let products = [
Product("8717644012208","Lynx Africa",2.49M)
Product("5010123730215","Listerine",2.49M)
Product("5000347009242","Aquafresh",1.99M)
Product("5045094763863","Ibuprofen", 1.99M)]
let Lookup code =
products |> Seq.tryFind (function Product(code',_,_) -> code' = code)```

Functions to be implemented in the task:

```[<AutoOpen>]
module Lines =
let saleTotal lines =
lines |> List.sumBy (fun line ->
match line with
| SaleLineItem(id,Product(_,_,price),quantity) -> price*quantity
| _ -> 0.0M
)
let tenderTotal lines =
raise (new System.NotImplementedException())
let cancelTotal lines =
raise (new System.NotImplementedException())```

Sale type:

```type Sale () =
let mutable items = []
member sale.AddItem (item:LineItem) = items <- item::items
member sale.TotalAmount = saleTotal items - cancelTotal items
member sale.OutstandingAmount = sale.TotalAmount - tenderTotal items
member sale.ChangeDue =
if sale.OutstandingAmount < 0M
then -sale.OutstandingAmount
else 0M```

Failing tests:

```open NUnit.Framework

[<TestFixture>]
module Tests =
open System.Diagnostics

[<Test>]
let ``Over tendering with cash should give change`` () =
let sale = Sale()
let product = Product("123", "3 Pay As you Go", 10.0M)
Assert.That(sale.ChangeDue = 10.0M)

[<Test>]
let ``Tendering full amount with card should leave no change`` () =
let sale = Sale()
let product = Product("123", "3 Pay As you Go", 10.0M)
Assert.That(sale.ChangeDue = 0.0M)

[<Test>]
let ``Cancelled items should not be charged`` () =
let sale = Sale()
let product = Product("123", "3 Pay As you Go", 10.0M)