3 people like it.

Finalizing Tesco purchase

The sample shows two different reprezentations of Tesco checkout. The first one stores scanned items - as a list of either purchase or cancel items - and the second stores final bill with product and total quantity. The snippet implements transformation that corresponds to finalizing the purchase.

Types representing Tesco products

 ```1: 2: 3: 4: 5: 6: ``` ``````type Code = string type Name = string type Price = decimal type Picture = string type Product = Product of Code * Name * Picture * Price type Quantity = decimal ``````

Representation using scanned items

 ```1: 2: 3: 4: 5: 6: ``` ``````type LineItem = | SaleLineItem of int * Product * Quantity | CancelLineItem of int /// Purchase is a list of items as they were scanned type LinePurchase = list ``````

Representation for the final bill

 ```1: 2: ``` ``````/// Immutable map stores products and the purchased quantity type FinalPurchase = Map ``````

Finalizing the purchase

 ``` 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: ``` ``````/// This function takes a list of scanned lines and /// produces a final bill. It first removes all cancelled /// items and then groups products to get total quantity. let calculateFinal (line:LinePurchase) : FinalPurchase = line |> Seq.choose (fun item -> match item with | SaleLineItem(id, prod, q) -> // Check if the item has been cancelled let cancelled = line |> Seq.exists (fun item -> match item with | CancelLineItem cancelId when cancelId = id -> true | _ -> false) if cancelled then None else Some (prod, q) | _ -> None ) // Group products and calculate total quantity |> Seq.groupBy (fun (prod, q) -> prod) |> Seq.map (fun (prod, items) -> prod, Seq.sumBy snd items) |> Map.ofSeq ``````
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type Name = string

Full name: Script.Name
type Price = decimal

Full name: Script.Price
Multiple items
val decimal : value:'T -> decimal (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.decimal

--------------------
type decimal = System.Decimal

Full name: Microsoft.FSharp.Core.decimal

--------------------
type decimal<'Measure> = decimal

Full name: Microsoft.FSharp.Core.decimal<_>
type Picture = string

Full name: Script.Picture
Multiple items
union case Product.Product: Code * Name * Picture * Price -> Product

--------------------
type Product = | Product of Code * Name * Picture * Price

Full name: Script.Product
type Code = string

Full name: Script.Code
type Quantity = decimal

Full name: Script.Quantity
type LineItem =
| SaleLineItem of int * Product * Quantity
| CancelLineItem of int

Full name: Script.LineItem
union case LineItem.SaleLineItem: int * Product * Quantity -> LineItem
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
union case LineItem.CancelLineItem: int -> LineItem
type LinePurchase = LineItem list

Full name: Script.LinePurchase

Purchase is a list of items as they were scanned
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
type FinalPurchase = Map<Product,Quantity>

Full name: Script.FinalPurchase

Immutable map stores products and the purchased quantity
Multiple items
module Map

from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> =
interface IEnumerable
interface IComparable
interface IEnumerable<KeyValuePair<'Key,'Value>>
interface ICollection<KeyValuePair<'Key,'Value>>
interface IDictionary<'Key,'Value>
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
member Add : key:'Key * value:'Value -> Map<'Key,'Value>
member ContainsKey : key:'Key -> bool
override Equals : obj -> bool
member Remove : key:'Key -> Map<'Key,'Value>
...

Full name: Microsoft.FSharp.Collections.Map<_,_>

--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val calculateFinal : line:LinePurchase -> FinalPurchase

Full name: Script.calculateFinal

This function takes a list of scanned lines and
produces a final bill. It first removes all cancelled
items and then groups products to get total quantity.
val line : LinePurchase
module Seq

from Microsoft.FSharp.Collections
val choose : chooser:('T -> 'U option) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.choose
val item : LineItem
val id : int
val prod : Product
val q : Quantity
val cancelled : bool
val exists : predicate:('T -> bool) -> source:seq<'T> -> bool

Full name: Microsoft.FSharp.Collections.Seq.exists
val cancelId : int
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val groupBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'Key * seq<'T>> (requires equality)

Full name: Microsoft.FSharp.Collections.Seq.groupBy
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val items : seq<Product * Quantity>
val sumBy : projection:('T -> 'U) -> source:seq<'T> -> 'U (requires member ( + ) and member get_Zero)

Full name: Microsoft.FSharp.Collections.Seq.sumBy
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val ofSeq : elements:seq<'Key * 'T> -> Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.ofSeq